BNU-FZH

fengzhenhua@outlook.com

ArchLinux是一款灵活、强大、可定制的Linux发行版,提供丰富的软件包和工具,支持滚动更新和多种桌面环境,拥有庞大的社区支持和方便的包管理器,适合各种用户需求和使用场景。Endeavour 是一个基于ArchLinux的轻量级和用户友好的发行版,预装了桌面环境和预配置的软件包,旨在提供一个无忧的ArchLinux体验。

阅读全文 »

通过dnsmasq 实现了本地 DNS 服务的功能,这大大加速的域名解析速度。但是最近在连接校园网时,发现每次连网配置文件/etc/resolv.conf都会被修改为校园网默认的配置,但是这样就无法设置为自动dnsmasq接管服务。

具体原因

当在eth接口启用DHCP后,本地resolv.conf文件将被修改,resolv.conf文件中的DNS地址将被改为从DHCP获取到的地址。这种从DHCP获得的DNS即是Peer DNS 启用DHCP后即便修改/etc/resolv.conf,不久又恢复成原样.

解决方法

  1. 断开网络
  2. /etc/resolv.conf修改为
    1
    2
    3
    4
    5
    # Generated by syndns
    nameserver 127.0.0.1
    nameserver 119.29.29.29
    nameserver 180.76.76.76
    nameserver 1.2.4.8
  3. 设置文件锁
    1
    sudo chattr +i /etc/resolv.conf
  4. 再次修改/etc/resolv.conf必须先解锁,命令为
    1
    sudo chattr -i /etc/resolv.conf

参考文章

一、问题

Shell下有时需要使用随机数,在此总结产生随机数的方法。计算机产生的的只是“伪随机数”,不会产生绝对的随机数(是一种理想随机数)。伪随机数在大量重现时也并不一定保持唯一,但一个好的伪随机产生算法将可以产生一个非常长的不重复的序列。

二、随机数

1、生成随机数的七种方法

(1)通过内部系统变量($RANDOM)

1
echo $RANDOM

生成0-32767之间的整数随机数,若超过5位可以加个固定10位整数,然后进行求余。

生成400000~500000的随机数
1
2
3
4
5
6
7
8
9
10
#!/bin/bash  
function rand(){
min=$1
max=$(($2-$min+1))
num=$(($RANDOM+1000000000)) #增加一个10位的数再求余
echo $(($num%$max+$min))
}
rnd=$(rand 400000 500000)
echo $rnd
exit 0

(2)使用awk的随机函数

1
awk 'BEGIN{srand();print rand()*1000000}' #可以加上if判断

(3)openssl rand产生随机数

openssl rand 用于产生指定长度个bytes的随机字符。-base64-hex对随机字符串进行base64编码或用hex格式显示。

1
2
openssl rand -base64 8 | md5sum | cut -c1-8 #八位字母和数字的组合,3a61800e
openssl rand -base64 8 | cksum | cut -c1-8 #八位数字,10784736

(4)通过时间获得随机数(date)

1
2
3
date +%s%N #生成19位数字,1287764807051101270
date +%s%N | cut -c6-13 #取八位数字,21793709
date +%s%N | md5sum | head -c 8 #八位字母和数字的组合,87022fda
生成1~50的随机数
1
2
3
4
5
6
7
8
9
10
#!/bin/bash 
function rand(){
min=$1
max=$(($2-$min+1))
num=$(date +%s%N)
echo $(($num%$max+$min))
}
rnd=$(rand 1 50)
echo $rnd
exit 0

(5)通过系统内唯一数据生成随机数(/dev/random及/dev/urandom)

/dev/random存储系统当前运行环境的实时数据,可看作系统某时的唯一值,提供优质随机数。

/dev/urandom是非阻塞随机数产生器,读取时不会产生阻塞,速度更快、安全性较差。

1
2
3
4
5
6
7
8
#32f1e953ac
cat /dev/urandom | head -n 10 | md5sum | head -c 10
#生成全字符的随机字符串,08?WU$ZU
cat /dev/urandom | strings -n 8 | head -n 1
#生成数字加字母的随机字符串,Ql2q9CXS,其中 strings -n设置字符串的字符数,head -n设置输出的行数。
cat /dev/urandom | sed -e 's/[^a-zA-Z0-9]//g' | strings -n 8 | head -n 1
#urandom的数据很多使用cat会比较慢,在此使用head读200行,cksum将读取文件内容生成唯一的表示整型数据,cut以” “分割然后得到分割的第一个字段数据
head-200/dev/urandom| cksum |cut-d" " -f1

(6)读取linux的uuid码

UUID码全称是通用唯一识别码 (Universally Unique Identifier, UUID),UUID格式是:包含32个16进制数字,以“-”连接号分为五段,形式为8-4-4-4-12的32个字符。linux的uuid码也是有内核提供的,在/proc/sys/kernel/random/uuid这个文件内。cat/proc/sys/kernel/random/uuid每次获取到的数据都会不同。

1
2
cat /proc/sys/kernel/random/uuid| cksum | cut -f1 -d" " #获取不同的随机整数,1675034933
cat /proc/sys/kernel/random/uuid| md5sum | cut -c1-8 #数字加字母的随机数,d69a7ebf
使用linux uuid 生成100~500随机数
1
2
3
4
5
6
7
8
9
10
#!/bin/bash 
function rand(){
min=$1
max=$(($2-$min+1))
num=$(cat /proc/sys/kernel/random/uuid | cksum | awk -F ' ' '{print $1}')
echo $(($num%$max+$min))
}
rnd=$(rand 100 500)
echo $rnd
exit 0

(7)从元素池中随机抽取取

1
2
3
pool=(a b c d e f g h i j k l m n o p q r s t 1 2 3 4 5 6 7 8 9 10)
num=${#pool[*]}
result=${pool[$((RANDOM%num))]}

用于生成一段特定长度的有数字和字母组成的字符串,字符串中元素来自自定义的池子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash 
length=8
i=1
seq=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
num_seq=${#seq[@]}

while [ "$i" -le "$length" ]
do
seqrand[$i]=${seq[$((RANDOM%num_seq))]}
let "i=i+1"
done

echo "The random string is:"
for j in ${seqrand[@]}
do
echo -n $j
done
echo

2、随机数应用

  1. 随机数在互联网中应用广泛如计算机仿真模拟、数据加密、网络游戏等,在登录某些论坛或游戏时,系统会产生一个由随机数字和字母组成的图片,用户必须正确输入,这是防止恶意攻击的很好的方法,因比较难破解图片格式的字符。其关键技术就是产生随机数,再使用ASP.NET等工具将这些字符串封装成图片格式以作为验证图片。

  2. 网络游戏中也常利用随机数完成一些功能,比如掷骰子、发扑克牌等。以下是连续掷1000次骰子,然后统计出1~6点的次数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #!/bin/bash 
    #RANDOM=$$
    PIPS=6
    MAX=1000
    throw=1

    one=0
    two=0
    three=0
    four=0
    five=0
    six=0
    count()
    {
    case "$1" in
    0) let "one=one+1";;
    1) let "two=two+1";;
    2) let "three=three+1";;
    3) let "four=four+1";;
    4) let "five=five+1";;
    5) let "six=six+1";;
    esac
    }

    while [ "$throw" -le "$MAX" ]
    do
    let "dice=RANDOM % $PIPS"
    count $dice
    let "throw=throw+1"
    done

    echo "The statistics results are as follows:"
    echo "one=$one"
    echo "two=$two"
    echo "three=$three"
    echo "four=$four"
    echo "five=$five"
    echo "six=$six"
    RANDOM产生的随机数基本在平均值左右浮动(即方差较小)。

  3. 批量创建10个系统帐号,密码随机 先看看指定用户密码的脚本:

    1
    2
    3
    4
    5
    6
    7
    #!/bin/bash 
    #批量创建10个系统帐号并设置密码,帐号和密码相同
    for name in `seq -w 10`
    do
    #非交互式的输入密码
    useradd linux$name && echo "linux$name" | passwd --stdin linux$name
    done
    10个用户用户名和密码相同都从linux-01到linux-10,再看看用户密码随机生成的脚本:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/bin/bash 
    #批量创建10个系统帐号并设置密码
    rm -f user.log
    for name in `seq -w 10`
    do
    #非交互式的输入随机密码
    password=`echo $RANDOM | md5sum | cut -c1-8`
    #可以使用password=`echo "date $RANDOM" | md5sum | cut -c3-11`
    #也可以使用password=`penssl rand -base64 8 | md5sum | cut -c1-8`
    useradd linux$name && echo password | passwd --stdin linux$name
    echo -e "user=linux$name \t passwd=$password" >> user.log #保存用户名密码以查阅
    done
    对比可以看出,随机生成密码的灵活性和保密性,管理员可以打开user.log文件,记录刚创建的十个用户的信息。

三、总结

  1. Shell产生伪随机数的函数$RANDOM,能方便地产生分布较平均的伪随机数,能满足大部分应用的需求。
  2. 产生随机数的方法还有很多并且可以扩展,扩展思路才能选择最近的方式。
  3. 完全引用自: shell产生随机数七种方法的实现

由于 linuxqq 是用 electron 写的,而且目前还有一些 bug, 当点击关闭按钮后程序仍然在后台运行。但是,想重新登录一下,却提示已经登录,而原来的聊天界面又找不到,所以必须完全关闭,然后再重新启动才行。 解决方法是借助pgrep打印所有相关进程,然后一同kill, 命令为

1
sudo kill $(pgrep qq)

由于工作和学习的需要,可能需要同时在一台电脑上维护多个 github 帐号,这时使用 Github-cli 同时使用多个帐号的 Token 认证后,然后就可以随时切换了。具体方法为:

登录认证帐号

1
gh auth login -p ssh --skip-ssh-key --with-token < your_token_here >

注意: 这条命令选择了 ssh的认证方式,所以需要提前配置好 ssh. 同时按 使用Github-Cli管理仓库 取得 Token.

切换帐号

1
gh auth switch -u < your_name_here >

gh auth 选项详解

gh help auth login
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
Authenticate with a GitHub host.

The default hostname is `github.com`. This can be overridden using the `--hostname`
flag.

The default authentication mode is a web-based browser flow. After completion, an
authentication token will be stored securely in the system credential store.
If a credential store is not found or there is an issue using it gh will fallback
to writing the token to a plain text file. See `gh auth status` for its
stored location.

Alternatively, use `--with-token` to pass in a personal access token (classic) on standard input.
The minimum required scopes for the token are: `repo`, `read:org`, and `gist`.

Fine-grained personal access tokens are not supported.

Alternatively, gh will use the authentication token found in environment variables.
This method is most suitable for "headless" use of gh such as in automation. See
`gh help environment` for more info.

To use gh in GitHub Actions, add `GH_TOKEN: ${{ github.token }}` to `env`.

The git protocol to use for git operations on this host can be set with `--git-protocol`,
or during the interactive prompting. Although login is for a single account on a host, setting
the git protocol will take effect for all users on the host.

Specifying `ssh` for the git protocol will detect existing SSH keys to upload,
prompting to create and upload a new key if one is not found. This can be skipped with
`--skip-ssh-key` flag.

For more information on OAuth scopes, <https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps/>.


USAGE
gh auth login [flags]

FLAGS
-p, --git-protocol string The protocol to use for git operations on this host: {ssh|https}
-h, --hostname string The hostname of the GitHub instance to authenticate with
--insecure-storage Save authentication credentials in plain text instead of credential store
-s, --scopes strings Additional authentication scopes to request
--skip-ssh-key Skip generate/upload SSH key prompt
-w, --web Open a browser to authenticate
--with-token Read token from standard input

INHERITED FLAGS
--help Show help for command

EXAMPLES
# Start interactive setup
$ gh auth login

# Authenticate against github.com by reading the token from a file
$ gh auth login --with-token < mytoken.txt

# Authenticate with specific host
$ gh auth login --hostname enterprise.internal

LEARN MORE
Use `gh <command> <subcommand> --help` for more information about a command.
Read the manual at https://cli.github.com/manual
Learn about exit codes using `gh help exit-codes`

参考文章

在编写脚本时避免不了使用密码,所以为了增强安全性,需要使用加密解密技术。本文记录几种加密解密的方法。

Python 与 Bash Shell 的结合

这个命令会让你输入一个字符串,然后会再输出一串加密了的数字.

1
2
3
4
# 加密代码[照直输入]:
python -c 'print reduce(lambda a,b: a*256+ord(b), raw_input("string: "), 0)'
# 解密代码[数字后+P]:
dc -e 输出的数字P

纯 Bash Shell, 含 VIM 的xxd

用 gtalk@gmail.com 作为明文,加密分两步也可以一步。

1
2
3
4
5
6
7
8
# 加密代码:
echo "gtalk@gmail.com" |xxd -ps -u
# 得到:6774616C6B40676D61696C2E636F6D0A
echo "ibase=16; 6774616C6B40676D61696C2E636F6D0A" |bc
# 得到:137514765985002236391382606438443478282
一步加密代码:
echo "ibase=16; $(echo "gtalk@gmail.com" |xxd -ps -u)" |bc
# 得到:137514765985002236391382606438443478282

Base64 编码

1
2
3
4
5
6
# 加密代码:
echo "gtalk@gmail.com" |base64 -i
# 得到:Z3RhbGtAZ21haWwuY29tCg==
# 解密代码:
echo "Z3RhbGtAZ21haWwuY29tCg==" |base64 -d
# 得到:gtalk@gmail.com

Base64 编码,这个很好很强大,适合写加密脚本

实现使用 base64 加密、解密字符串并赋值给变量。网上绝大多数是使用 echo 管道实现 加密和解密字符串的输出。

1
2
3
4
5
pwd=$( base64 -d <<< MQo= )  # 解码
in=$( base64 <<< "123456") # 加密
# 或者
test=$(printf "%s""123456" | base64) # 加密
test=$(printf "%s" MTIzNDU2| base64 -d) # 解密

参考文章

在 Markdown 中添加目录(Table of Contents, ToC)并不是直接支持的功能,但是你可以手动创建一个简单的目录,使用链接和锚点来指向文档中的各个部分。首先,在你想链接到的标题或段落前设置一个锚点(ID),然后在目录部分创建指向这些锚点的链接。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 目录
- [简介](#简介)
- [安装](#安装)
- [使用方法](#使用方法)

# 简介
这是介绍内容。

## 安装
这是安装说明。

## 使用方法
这是使用方法。

注意:不是所有的Markdown解析器都支持通过标题自动创建锚点链接。有些解析器可能会需要你显式地为每个标题定义一个唯一的ID,像这样:

1
## <a name="安装"></a>安装

当编写复杂的 Shell 脚本时,了解脚本在何处停止执行可以极大地帮助调试和优化。本文将介绍几种在 Shell 脚本中判断脚本停止位置的方法。

目录

添加日志记录

通过在脚本的关键位置添加日志记录,可以帮助跟踪脚本的执行进度。例如:

1
echo "Script has reached step 1" >> script.log 

这行命令会在每次执行到该行时向 script.log 文件追加一条消息。

启用调试模式

你可以使用 -x 选项来启用 bash 的调试模式,这会让它打印出执行的每个命令:

1
bash -x ./your_script.sh

或者在脚本内部临时开启调试:

1
2
3
set -x
# 你的代码
set +x

这样可以在脚本的特定部分开启或关闭调试输出。

错误捕获和通知

使用 trap 命令可以在发生错误时执行特定的命令,比如发送通知或写入日志:

1
trap 'echo "Error at line $LINENO: $BASH_COMMAND"' ERR

这将在任何命令失败时触发,并打印出错误发生的行号和命令。

检查退出状态

每个命令执行后都会返回一个退出状态码,通常0表示成功,非零值表示错误。可以通过检查 $? 变量来决定是否继续执行:

1
2
3
4
5
command
if [ $? -ne 0 ]; then
echo "Command failed"
exit 1
fi

这种方式确保只有当上一条命令成功时才会继续执行。

在 Shell 脚本中避免输入 sudo 密码的方法有几种,但每种方法都有其适用场景和安全考量。以下是几种常见的方法:

1. 修改 /etc/sudoers 文件

你可以编辑 /etc/sudoers 文件(推荐使用 visudo 命令以确保语法正确),为特定用户或用户组添加不需要密码的权限。

例如,要允许用户 username 在不输入密码的情况下运行所有命令,可以添加如下行:

1
username ALL=(ALL) NOPASSWD:ALL 

如果你想限制到特定命令,比如只允许不输入密码地运行 apt-get update,可以这样做:

1
username ALL=(ALL) NOPASSWD:/usr/bin/apt-get update

2. 使用sudo -S和环境变量

虽然这不是最推荐的安全实践,但在某些情况下你可能需要自动化流程,并且能够通过环境变量传递密码。你可以设置一个环境变量来保存密码,并结合 echosudo -S 来实现这一点。但是,请注意这种方法存在安全风险,因为密码可能会被其他进程看到。

1
2
export SUDO_PASSWORD="your_password_here"
echo "$SUDO_PASSWORD" | sudo -S command_to_run

警告: 这种方式并不安全,应该尽量避免使用。

3. 使用sudo-n选项

-n 选项可以让 sudo 尝试非交互式执行命令,即如果当前用户没有足够的权限或缓存的凭证已过期,则不会提示输入密码而是直接失败。这可以用于检查是否可以在不提供密码的情况下执行命令。

1
sudo -n command_to_run

4. 利用sudo的时间戳

sudo 会缓存用户的认证一段时间(默认是15分钟)。如果你在一个脚本中多次调用 sudo,那么在第一次成功输入密码后,在这段时间内后续的 sudo 调用将不再要求密码。

安全建议

无论选择哪种方法,都应该谨慎行事,确保最小权限原则 ( Principle of Least Privilege ) 得以遵守,即给予用户完成工作所需的最少权限。修改系统配置文件如 /etc/sudoers 应该非常小心,错误的配置可能导致安全漏洞或系统无法正常工作。

GitHub CLI 简介

GitHub CLI 是一个用于通过命令行与 GitHub 进行交互的强大工具。它允许开发者和用户管理存储库、拉取请求、问题和其他 GitHub 资源,而无需离开终端。

主要功能

  1. 仓库管理:创建、克隆、列出和删除仓库。
  2. 拉取请求:查看、创建、合并和关闭拉取请求。
  3. 问题跟踪:创建、列表、评论和关闭问题。
  4. 项目管理:管理和操作 GitHub Projects。
  5. 代码审查:检查更改、提交评论和批准或拒绝拉取请求。
  6. 扩展性:支持通过脚本和插件进行扩展。

安装 Github-Cli

1
sudo pacman -S github-cli

基本使用

在 GitHub 上取得 Personal Access Token

1. 登录 GitHub 账户

  • 打开 GitHub 并使用你的凭据登录。

2. 进入开发者设置

  • 点击右上角的头像图标。
  • 从下拉菜单中选择 Settings

3. 导航到“Developer settings”

  • 在左侧边栏中找到并点击 Developer settings

4. 生成新的个人访问令牌

  • Developer settings 中,点击 Personal access tokens
  • 点击 Tokens (classic)Fine-grained tokens,具体取决于你需要的权限范围。
    • 如果选择 Tokens (classic)
      • 点击 Generate new token
      • 填写令牌描述。
      • 选择所需的权限范围(例如,repo 表示对仓库的完全控制)。
      • 点击 Generate token
    • 如果选择 Fine-grained tokens
      • 点击 Generate new token
      • 填写令牌名称和描述。
      • 配置资源访问权限(例如,特定组织或仓库)。
      • 配置所需的作用域(例如,读取和写入仓库)。
      • 点击 Generate token

5. 保存令牌

  • 生成后,你会看到新创建的令牌。非常重要的是,此时需要复制并安全地存储这个令牌,因为一旦离开页面,你就无法再次查看该令牌。
  • 不要将令牌泄露给他人,并确保将其存储在一个安全的地方。

6. 使用令牌

  • 你可以使用这个令牌来进行身份验证,例如,在命令行工具中使用 GitHub CLI 登录:
    1
    gh auth login --with-token < your_token_here >

    在本地配置 ssh 后, 可以在第6步中使用令牌登录,选择 ssh, 这种方法可以方便的创建、删除仓库等操作而不用登录网页。

基本操作

  1. 登录和认证(按提示,一步一步认证即可)

    1
    gh auth login

  2. 仓库管理

    新建、列出、查看、删除仓库
    1
    2
    3
    4
    gh repo create my-new-repo --public
    gh repo list
    gh repo view owner/repo
    gh repo delete owner/repo

  3. 拉取请求

    创建、列出、查看、合并、关闭请求
    1
    2
    3
    4
    5
    gh pr create --title "Fix bug" --body "This PR fixes a critical bug."
    gh pr list
    gh pr view 123
    gh pr merge 123
    gh pr close 123

  4. 问题跟踪

    创建、列出、查看、关闭issue
    1
    2
    3
    4
    gh issue create --title "Bug report" --body "I found a bug..."
    gh issue list
    gh issue view 456
    gh issue close 456

  5. 分支管理

    列出、创建、删除分支
    1
    2
    3
    gh branch list
    gh branch create new-feature
    gh branch delete old-feature

  6. 发布管理

    创建、列出、查看release
    1
    2
    3
    gh release create v1.0.0
    gh release list
    gh release view v1.0.0

  7. 用户信息

    查看当前用户、其他用户
    1
    2
    gh api user
    gh api users/username

  8. 组织管理

    列出、查看组织
    1
    2
    gh org list
    gh org view organization-name