假设要将脚本 test.sh 设置为可执行,需要:
chmod +x test.sh 改变文件模式为可执行;./ 指定路径,比如先将当前工作区设置为脚本所做位置(使用 cd 命令),然后: ./test.sh如果执行时出现异常信息:
/bin/sh^M: bad interpreter: No such file or directory
原因:
是我们在 windows 下编写的脚本文件,直接放到 Linux 默认的是 dos 模式的文本,不被识别,需要处理下。
解决办法有 3 种:
- 用 vim 打开脚本文件,在命令模式下输入:
:set ff=unix, 然后输入:wq保存退出就可以了。(set ff=unix是告诉 Vim,将文件的换行符从原来的格式转换为 Unix 格式。)- 在 windows下转换脚本格式,用 Notepad 改变文件格式即可。File–>Conversions–>DOS->UNIX
- 在 Linux 下新建一个 .sh 文件,然后复制粘贴过去也是可以的。
感谢网友 QC(_) 的博文。
${0}、${1}、${2}、${3}、${#}、${@}${0} 表示脚本或函数的名称。
${1}、${2}、${3} 等表示脚本或函数的第一、第二、第三个参数,以此类推。
${#} 表示传递给脚本的参数个数
`${@} 表示列出所有参数
举一个例子:
#!/bin/bash
echo "Shell name: ${0}."
echo "Number of parameters: ${#}."
echo "The first parameter is ${1}."
echo "The second parameter is ${2}."
echo "The parameter list is ${@}."
exit 0
脚本命名为 shell_arg.sh,运行这个脚本:
./shell_arg.sh 1 2 3
输出内容为:
Shell name: ./shell_arg.sh.
Number of parameters: 3.
The first parameter is 1.
The second parameter is 2.
The parameter list is 1 2 3.
注意的是,¥{0} 会包含脚本的路径。
$() 与命令 basename$() 表示命令替换。这是一种特殊的变量,它会将括号内的命令执行的结果赋值给变量。
#!/bin/bash
script_name="$(basename "${0}")"
echo "${script_name}"
exit 0
运行这个脚本:./shell_arg.sh
输出内容为:shell_arg.sh
在这个例子中,命令 basename 用于提取文件路径中的文件名,并显示基本文件名。
具体而言,basename命令从文件路径中删除目录路径和符号链接,只保留文件名部分。这对于提取文件名而不需要完整的文件路径非常有用。
比如 basename /path/to/file.txt ,输出的内容为 file.txt。
readlink 和 dirnamereadlink 命令用于读取符号链接(symbolic link)所指向的实际文件路径。
符号链接是一种特殊类型的文件,它包含了另一个文件或目录的引用。当读取符号链接时,实际上读取的是链接目标文件的路径,而不是链接文件本身。readlink命令允许用户通过解析符号链接来获取实际文件的路径。语法为:
readlink [-fhlnr] [-m pattern] [file...]
主要选项和功能如下:
-f:解析路径名中的符号链接,并将其替换为实际路径。
-l:将输入作为符号链接对待,而不是普通文件。
-n:不进行换行处理,将输出直接打印到标准输出。
-r:递归解析符号链接,直到找到最终目标。
-m:使用模式匹配来解析符号链接。
dirname 是一个常用的命令行工具,它用于提取文件路径中的目录部分。
具体来说,dirname 命令接受一个文件路径作为参数,并返回该路径所在的目录路径。它删除了文件名和文件扩展名部分,只保留目录路径。
#!/bin/bash
script_name="$(basename "${0}")"
script_path="$(readlink -f "${0}")"
script_dir="$(dirname "${script_path}")"
echo "${script_name}"
echo "${script_path}"
echo "${script_dir}"
exit 0
运行这个脚本:./shell_arg.sh
输出内容为:
script_name is shell_arg.sh
script_path is /home/zhzhchang/Documents/Vscode-shell-test/shell_arg.sh
script_dir is /home/zhzhchang/Documents/Vscode-shell-test
if 语句的测试条件在Linux shell编程中,if语句可以用于进行条件测试。以下是常见的测试条件:
文件测试:
-f:检查文件是否存在且是一个普通文件。-d:检查目录是否存在。-e:检查文件或目录是否存在。-r:检查文件是否可读。-w:检查文件是否可写。-x:检查文件是否可执行。-h:文件或目录是否是符号链接字符串测试:
-z:检查字符串是否为空。-n:检查字符串是否非空。整数比较:
-eq:等于-ne:不等于-lt:小于-gt:大于-le:小于等于-ge:大于等于逻辑测试:
-a:与(AND)-o:或(OR)!:非(NOT)字符串比较:
=:字符串相等!=:字符串不相等-z 或 != 非空字符串(长度为零)-n 或 != 空字符串(长度非零)数值比较(需使用双括号):
((a == b)):等于((a != b)):不等于((a < b)):小于((a > b)):大于((a <= b)):小于等于((a >= b)):大于等于需要使用双括号来表示数值比较。set -e 与 set +eset -e 是一个用来设置脚本行为的命令。当脚本遇到任何错误时,它将会立即终止脚本的执行。set -e 通常用在脚本的开始部分,以确保脚本在遇到任何错误时能够立即停止,这样可以帮助开发者更快地定位和修复问题。
set +e 用于取消上述设置。
$?在Unix和类Unix系统中,每个运行中的进程都有一个退出状态码(也称为返回值),当进程结束时返回给操作系统。这个退出状态码可以用来表示进程是否成功地完成了它的任务,或者是否遇到了错误。在 shell 脚本中,你可以使用 $? 来检查上一条命令的退出状态,以此为基础来决定下一步的操作。通常,0 表示成功,非零值 表示错误。
sleep 和 usleepLinux shell环境下,常用的延时函数包括:
unsigned int sleep(unsigned int seconds)。例如:sleep(1) 表示延时一秒。int usleep(useconds_t usec)。注意,usec 需要小于 1000000。例如,usleep(1000) 表示延时 1 秒(1000 微秒)。trapfunction cleanup() {
# ...
}
trap cleanup EXIT
在Shell脚本中,trap 是一个内置命令,用于捕获和处理信号。这里的 trap cleanup EXIT 意味着当脚本收到 EXIT 信号(通常是在脚本完成或由于某种错误导致脚本中断时发送的)时,它会执行 cleanup 函数。
信号的名字定义在头文件 signal. h 中,
EXIT:退出,在脚本完成或由于某种错误导致脚本中断时发送的退出信号。INT:中断,当用户按下Ctrl+C时,会发送中断信号。QUIT:退出,当用户按下Ctrl+\时,会发送退出信号。ABRT:中止,通常印某些严重的错误而引发ALRM:报警,通常用于处理超时TERM:终止,通常在系统关机时发送shift在Shell脚本中,shift 命令用于将参数列表向左移动。shift 2 的意思是将参数列表向左移动两位。举个例子,如果你有如下的参数列表:arg1 arg2 arg3 arg4,执行 shift 2 后,原来的 arg1 和 arg2 会被丢弃,新的参数列表变成:arg3 arg4。
source作用有点类似于 C 中的 #include 指令,具体来说,当你在 source 命令后指定一个文件名(例如 source test.sh ),Shell 会首先读取 test.sh 文件中的所有命令,然后将这些命令插入到当前 Shell 环境中执行。这意味着,文件中定义的任何变量或函数都可以在当前 Shell 环境中直接使用。
source 命令的一个常见用途是加载环境变量。如果你修改了 .bashrc 或其他配置文件,你可以使用 source 命令让这些修改立即生效,而无需重新登录。例如,你可以在 .bashrc 文件中设置某些环境变量,然后在你需要这些环境变量的 Shell 会话中使用source 命令加载它们。
pushd在 Shell 中,pushd 是一个命令,用于将当前目录压入目录栈,并切换到指定的目录。具体而言,pushd 会将当前目录的路径保存到栈中,然后通过改变当前工作目录来切换到指定的目录。
以通过 popd 命令返回之前的目录。
需要注意的是,pushd 和 popd 命令是针对当前 Shell 会话的,而不是针对脚本本身。这意味着在脚本中执行这些命令只会影响当前 Shell 会话中的工作目录,而不会影响脚本执行完毕后的工作目录。
command > output.txt
这将执行 command 并将输出写入 output.txt 文件中。如果文件不存在,则会创建该文件;如果文件已存在,则会覆盖其内容。
command >> output.txt
类似于上面的方法,但是输出将追加到 output.txt 文件的末尾,而不是覆盖文件内容。
command > output.txt 2>&1
这会将标准输出和错误输出都重定向到 output.txt 文件中。2>&1 表示将标准错误(file descriptor 2)重定向到标准输出(file descriptor 1)。
/dev/null,也就是说,不显示任何输出信息:command > /dev/null 2>&1
cut -d'=' -f1
是一个用于处理文本的命令。这个命令的作用是按等号( ‘=’ )作为分隔符( -d 选项指定),选择每行的第一个字段( -f1 选项指定)。通常,这个命令用于处理键值对文本,例如在处理 INI 文件或环境变量导出时,它能提取出等号前的键。
user_pass="$(date +%s | sha256sum | base64 | head -c 8)"
这段代码是在 Bash shell 环境中生成一个用户密码。它的工作方式如下:
date +%s:这部分生成一个当前时间的 Unix 时间戳。
sha256sum:这个命令对前面生成的时间戳进行 SHA-256 哈希运算。
base64:这个命令将上一步的哈希结果进行 Base64 编码,使其变成一个可打印的字符。
head -c 8:最后这个命令从编码后的结果中选取前8个字符。
因此,这段代码生成的是一个8个字符长度的Base64编码的SHA-256哈希值,它基于当前的Unix时间戳。这样的用户密码由于其随机性和基于时间的特性,可以提供较好的安全性。
nargs=$#;
target_rootdev=${!nargs};
$#是特殊的Shell变量,代表命令行参数的个数,这就是 nargs 的值。${!nargs} 是间接引用,它引用的是 nargs 变量的值所代表的变量。在这个上下文中,nargs 的值是$#,代表命令行参数的个数,因此 ${!nargs} 就引用了第 $# 个参数。opstr+="b:c:d:e:f:h:i:k:m:n:o:p:rs:t:u:v:w:x:z:B:C:F:G:I:K:L:M:N:P:R:S:Z:-:";
while getopts "${opstr}" OPTION; do
case $OPTION in
b) BCTFILE=${OPTARG}; ;;
Z) zflag="true"; ;; # cmdline only
-) case ${OPTARG} in
no-root-check) no_root_check=1; ;;
no-flash) no_flash=1; ;;
esac;;
*) usage allunknown 1; ;;
esac;
done
opstr+="b:c:d:e:f:h:i:k:m:n:o:p:rs:t:u:v:w:x:z:B:C:F:G:I:K:L:M:N:P:R:S:Z:-:";:这一行定义了一个字符串 opstr,并向其添加了多个字符,每个字符后面都有一个冒号。这些字符将作为选项用于后面的 getopts 命令。while getopts "${opstr}" OPTION; do:这是一个 while 循环,它将遍历通过 opstr 定义的每个选项。getopts 命令将解析命令行参数,并将每个选项的名称存储在变量 OPTION 中。case $OPTION in:这是一个 case 语句,它将根据 OPTION 的值来执行不同的操作。接下来,代码定义了与每个选项对应的操作。例如,当选项是 b 时,将把变量 BCTFILE 设置为命令行参数的值。类似的,对于其他选项也有类似的操作。
*) usage allunknown 1; ;;):这是一个通配符模式,用于处理不匹配任何特定选项的情况。在这种情况下,将执行 usage allunknown 1 命令,但该命令在给定的代码段中没有定义。esac; done:这是 case 语句和 while 循环的结束标记。另外,在选项 - 的情况下,根据命令行参数的值,将执行不同的操作。例如,如果参数是 no-root-check,则将变量 no_root_check 设置为1,以此类推。
这个脚本主要用于处理命令行参数,并根据参数的值执行相应的操作。
declare -F -f process_fuse_level > /dev/null 2>&1;
这段代码用于检查是否存在一个名为 process_fuse_level 的函数。
declare -F -f process_fuse_level 这句代码会检查是否存在名为 ‘process_fuse_level’ 的函数,如果存在,该函数会被声明为只读。
然后 /dev/null 2>&1 将标准输出和错误输出都重定向到 /dev/null,也就是说,不显示任何输出信息。
总的来说,这段代码用于在不产生任何输出(包括错误)的情况下检查一个函数是否存在。
tegrarcm --uid | grep BR_CID | cut -d' ' -f2
tegrarcm --uid 输出的信息为:BR_CID: 0x32101001642a170814000000120204c0grep 命令用于搜索文本,在给定的文件或标准输入中搜索匹配 ‘BR_CID’ 的行,其输出通过管道传送给 cut 命令cut 命令用于从文本中提取字段,这里的 -d' ' 指定了字段分隔符为空格,-f2 表示提取第二个字段。因此,cut 命令将从 grep 命令输出的每一行中提取第二个字段(以空格分隔),并将其输出到标准输出。ECID="0x32101001642a170814000000120204c0";
flval="${ECID:2:1}"
ECID 的变量,并赋值为一个十六进制的字符串。flval="${ECID:2:1}":这一行使用了字符串切片操作。${ECID:2:1} 表示从 ECID 的第 2 个字符开始(索引从 0 开始计算),截取长度为 1 的片段。所以这行代码将 ECID 的第 3 个字符(在 ECID 中索引为 2 的字符)赋值给 flval。这段代码在 ECID 为 “0x32101001642a170814000000120204c0” 的情况下,flval 的值将是 “3”。
:-ROOTFS_TYPE="${ROOTFS_TYPE:-ext4}";
这行 Shell 代码定义了一个变量 ROOTFS_TYPE,如果 ROOTFS_TYPE 这个变量在之前已经定义过,并且其值不是空字符串,那么这行代码就不会改变 ROOTFS_TYPE 的值。但如果 ROOTFS_TYPE 这个变量之前没有定义,或者其值为空字符串,那么这行代码就会将其值设置为 ext4。这是 Shell 中的默认参数扩展(Parameter Expansion)的用法。
evaleval 命令用于执行存储在字符串中的命令,并返回结果。
这个命令会解析并执行其参数指定的字符串中的命令,然后将结果输出到标准输出。例如,如果你有一个字符串包含了一个命令,你可以使用 eval 来执行那个命令。
注意,由于 eval 会执行字符串中的任意命令,因此在使用时需要特别小心,避免执行不安全的命令。
pre_deb_list=()
cp ./u-boot{,.bin,.dtb,-dtb.bin} $HOME
./u-boot{,.bin,.dtb,-dtb.bin}: 这部分用于指定要复制的文件。这里使用了文件名模式匹配,该命令将匹配以 u-boot 开头的四个文件:
if ! which git > /dev/null ; then
echo "ERROR: git is not installed. If your linux distro is 10.04 or later,"
echo "git can be installed by 'sudo apt-get install git-core'."
exit 1
fi
which git 尝试找到 git 命令的路径。如果 git 已经安装在系统上,这个命令将返回 0 并输出 git 的路径。否则,它什么都不输出并返回一个非零的退出状态。而在 Shell 脚本中,返回 0 表示成功,这与 C 语言不同,例如:if some_command; then
echo "Command succeeded"
else
echo "Command failed"
fi
在上述脚本中,如果 some_command 返回 0,那么 if 语句判断为 true ,执行 then 后面的代码块;如果 some_command 返回非 0 值,那么 if 语句判断为 false,执行 else 后面的代码块。
> /dev/null 将 which git 的任何输出重定向到 /dev/null,这意味着任何输出都将被丢弃,不会显示出来。fio#读测试
fio -filename=test2g -direct=1 -rw=read -bs=1M -size=2G -numjobs=64 -runtime=10 -group_reporting -name=file1
#写测试
fio -filename=test2g -direct=1 -rw=write -bs=1M -size=2G -numjobs=64 -runtime=10 -group_reporting -name=file1
-filename=test2g: 指定测试的文件名为’test2g’。注意会在工作目录下生成 test2g 文件,测试完成后要手动删除-direct=1: 直接I/O模式,绕过页缓存。-rw=read: 测试读取操作,替换之前的write。-rw=write表示这是写入测试-bs=1M: 块大小设为1M。-size=2G: 测试的文件大小为2G。-numjobs=64: 同时进行的作业数设为64。-runtime=10: 每个作业运行10秒。-group_reporting: 启用组报告模式,可以同时报告所有作业的总体情况。-name=file1: 给这个测试任务命名为’file1’。fio-3.1
Starting 64 processes
file1: Laying out IO file (1 file / 2048MiB)
Jobs: 64 (f=64): [R(64)][100.0%][r=88.0MiB/s,w=0KiB/s][r=88,w=0 IOPS][eta 00m:00s]
file1: (groupid=0, jobs=64): err= 0: pid=4780: Thu Mar 2 15:07:30 2023
read: IOPS=88, BW=88.8MiB/s (93.1MB/s)(952MiB/10722msec)
clat (msec): min=14, max=10702, avg=695.81, stdev=2470.19
lat (msec): min=14, max=10702, avg=695.81, stdev=2470.19
clat percentiles (msec):
| 1.00th=[ 22], 5.00th=[ 23], 10.00th=[ 23], 20.00th=[ 23],
| 30.00th=[ 23], 40.00th=[ 23], 50.00th=[ 23], 60.00th=[ 23],
| 70.00th=[ 23], 80.00th=[ 23], 90.00th=[ 372], 95.00th=[ 9597],
| 99.00th=[10537], 99.50th=[10671], 99.90th=[10671], 99.95th=[10671],
| 99.99th=[10671]
bw ( KiB/s): min= 2048, max=47772, per=25.31%, avg=23012.47, stdev=21602.27, samples=80
iops : min= 2, max= 46, avg=22.20, stdev=20.83, samples=80
lat (msec) : 20=0.11%, 50=88.97%, 500=2.10%, 750=2.31%, >=2000=6.51%
cpu : usr=0.00%, sys=0.07%, ctx=1095, majf=0, minf=17569
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwt: total=952,0,0, short=0,0,0, dropped=0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
READ: bw=88.8MiB/s (93.1MB/s), 88.8MiB/s-88.8MiB/s (93.1MB/s-93.1MB/s), io=952MiB (998MB), run=10722-10722msec
Disk stats (read/write):
mmcblk0: ios=1886/1, merge=0/3, ticks=1126360/4332, in_queue=1321704, util=98.65%
sudo du -ah --max-depth=1 /
-a:显示所有的文件和目录,而不是只显示目录的总大小-h:以人类可读模式显示(使用 K、M、G 等单位)--max-depth:限制递归深度为 1。/:从根目录开始计算dpkg-query -Wf '${Installed-Size;8} KiB \t${Package;-30}\t${binary:Summary}\n'
dpkg-query -Wf '${Installed-Size;8} KiB \t${Package;-30}\t${binary:Summary}\n' | sort -n -t$'\t' -k 1,1
读后有收获,资助博主养娃 - 千金难买知识,但可以买好多奶粉 (〃‘▽’〃)
