假设要将脚本 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(_) 的博文。
2、在 windows下转换脚本格式,用 Notepad 改变文件格式即可。File–>Conversions–>DOS->UNIX。
3、在 Linux 下新建一个 .sh 文件,然后复制粘贴过去也是可以的。
————————————————
版权声明:本文为CSDN博主「QC(_)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_27195727/article/details/115698995
${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
和 dirname
readlink
命令用于读取符号链接(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 +e
set -e
是一个用来设置脚本行为的命令。当脚本遇到任何错误时,它将会立即终止脚本的执行。set -e
通常用在脚本的开始部分,以确保脚本在遇到任何错误时能够立即停止,这样可以帮助开发者更快地定位和修复问题。
set +e
用于取消上述设置。
$?
在Unix和类Unix系统中,每个运行中的进程都有一个退出状态码(也称为返回值),当进程结束时返回给操作系统。这个退出状态码可以用来表示进程是否成功地完成了它的任务,或者是否遇到了错误。在 shell 脚本中,你可以使用 $?
来检查上一条命令的退出状态,以此为基础来决定下一步的操作。通常,0
表示成功,非零值
表示错误。
sleep
和 usleep
Linux shell环境下,常用的延时函数包括:
unsigned int sleep(unsigned int seconds)
。例如:sleep(1) 表示延时一秒。int usleep(useconds_t usec)
。注意,usec 需要小于 1000000。例如,usleep(1000) 表示延时 1 秒(1000 微秒)。trap
function 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)的用法。
eval
eval
命令用于执行存储在字符串中的命令,并返回结果。
这个命令会解析并执行其参数指定的字符串中的命令,然后将结果输出到标准输出。例如,如果你有一个字符串包含了一个命令,你可以使用 eval
来执行那个命令。
注意,由于 eval
会执行字符串中的任意命令,因此在使用时需要特别小心,避免执行不安全的命令。
pre_deb_list=()
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