Shell脚本常见特殊命令用法记录
Shell脚本中常见特殊命令用法记录
1、信号捕获:trap
trap "commands" signals # 接收到signals指定的信号时,执行commands命令。
trap signals # 如果没有指定命令就是恢复 signals的动作。比如 trap INT 就是恢复Ctrl+C。
trap "" signals # 忽略信号signals
trap -l # 列出所有的信号
[root@localhost ~]# trap -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
# shell"伪信号"
信号名 产生时间
EXIT 从一个函数中退出或整个脚本执行完毕
ERR 当一条命令返回非0状态
DEBUG 脚本中每条命令执行之前
# Example:
#!/bin/sh
set -e
lockfile=/tmp/lockfile
[ -f $lockfile ] && echo It is running! && exit 1
function finish()
{
rm -f "$lockfile"
}
touch $lockfile && trap finish EXIT
2、文件路径中获取文件目录:dirname
[root@localhost ~]# dirname /usr/bin/
/usr
[root@localhost ~]# dirname .ssh/
.
# Example:
#!/bin/sh
set -e
CURDIR=$(cd $(dirname $0); pwd)
cd $CURDIR
# 在脚本目录下生成测试文件
echo "hello world" > test.txt
3、从标准输入替换环境变量到标准输出:envsubst
[root@localhost ~]# envsubst
I am $USER,my home directory is $HOME.
I am root,my home directory is /root.
[root@localhost ~]# echo '$HOME'
$HOME
[root@localhost ~]# echo '$HOME' | envsubst
/root
# Example:
#!/bin/sh
set -e
envsubst < /root/envfile" > envfile.out
[root@localhost ~]# cat envfile
I am $USER,my home directory is $HOME.
[root@localhost ~]# cat envfile.out
I am root,my home directory is /root.
4、特殊设备用以提供随机数:random/urandom
# /dev/random 是真随机数生成器,它会消耗熵值来产生随机数,同时在熵耗尽的情况下会阻塞,直到有新的熵生成。
# /dev/urandom 是伪随机数生成器,它根据一个初始的随机种子(这个种子来源就是熵池中的熵)来产生一系列的伪随机数,而并不会在熵耗尽的情况下阻塞。
# linux是根据系统的熵池来产生随机数的。熵池就是系统当前的环境噪音,环境噪音的来源很多,键盘的输入、鼠标的移动、内存的使用、文件的使用量、进程数量等等。当系统的熵不够大的时候,则系统产生的随机数随机效果就不是很好,也就是说更容易被人猜测出来。
# Example:
[root@localhost ~]# random_pwd=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 8)
[root@localhost ~]# echo $random_pwd
DmL3uaPs
[root@localhost ~]# random_pwd=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 8)
[root@localhost ~]# echo $random_pwd
kvBK1xN8
5、创建特殊文件:mknod /mkfifo
[root@localhost ~]# ls -l /dev/vdb
brw-rw---- 1 root disk 252, 16 Dec 15 21:22 /dev/vdb
# 查看/dev/vdb,设备号依次为252、16
[root@localhost ~]# rm -rf /dev/vdb
[root@localhost ~]# ls -l /dev/vdb
ls: 无法访问/dev/vdb: 没有那个文件或目录
# Example:
# mknod创建块设备
[root@localhost ~]# mknod /dev/vdb b 252 16
[root@localhost ~]# ls -l /dev/vdb
brw-rw---- 1 root disk 252, 16 Dec 15 21:22 /dev/vdb
# mknod创建命名管道
[root@localhost ~]# mknod fifofile p
# mkfifo命令创建命名管道
[root@localhost ~]# mkfifo fifofile2
[root@localhost ~]# ls -l fifofile*
prw-r--r-- 1 root root 0 Mar 10 11:04 fifofile
prw-r--r-- 1 root root 0 Mar 10 11:12 fifofile2
6、使用命令替换shell进程与文件描述符操作:exec
# 使用新的进程去代替原来的进程上下文,其进程UID不变,原进程后续的命令将不再执行。
[root@localhost ~]# cat exec.sh
#!/bin/bash
echo "command a"
exec echo "command b"
echo "command c"
[root@localhost ~]# chmod +x exec.sh
[root@localhost ~]# ./exec.sh
command a
command b
# 操作文件描述符
command > filename 把标准输出重定向到一个文件中
command >> filename 把标准输出重定向到一个文件中(追加)
command 1 > fielname 把标准输出重定向到一个文件中
command > filename 2>&1 把标准输出和标准错误一起重定向到一个文件中
command 2 > filename 把标准错误重定向到一个文件中
command 2 >> filename 把标准输出重定向到一个文件中(追加)
command >> filename 2>&1 把标准输出和标准错误一起重定向到一个文件中(追加)
command < filename >filename2 把command命令以filename文件作为标准输入,以filename2文件作为标准输出
command < filename 把command命令以filename文件作为标准输入
command << delimiter 把从标准输入中读入,直至遇到delimiter分界符
command <&m 把文件描述符m作为标准输入
command >&m 把标准输出重定向到文件描述符m中
command &m<&- 关闭文件描述符m
exec 3</tmp/test.txt # 以“只读方式”打开文件/tmp/test.txt,文件描述符对应为3
exec 3>/tmp/test.txt # 以“只写方式”打开文件/tmp/test.txt,文件描述符对应为3
exec 3<>/tmp/test.txt # 以“读写方式”打开文件/tmp/test.txt,文件描述符对应为3
exec 3<&- # 关闭文件描述符3
# Example:
#!/bin/sh
set -e
fifofile=fifo.$(date "+%s.%N")
mkfifo $fifofile
# 持续读取命名管道$fifofile的内容并重定向到日志中
cat $fifofile >> log.$(date "+%Y%m%d%H%M%S") &
# 将标准输出和标准错误重定向到命名管道$fifofile
exec 1>$fifofile 2>&1
echo "hello world"
# 该脚本的目的是将脚本运行中的所有回显(标准输出和标准错误)全部保存到日志文件中
[root@localhost ~]# cat log.20230310115306
hello world
7、目录压栈和出栈:pushd/popd
[root@localhost ~]# pushd /opt
/opt ~
[root@localhost opt]# pushd
~ /opt
[root@localhost opt]# popd
~
[root@localhost ~]# popd
-bash: popd: directory stack empty
# Example:
#!/bin/sh
set -e
# 当前目录压栈
pushd . > /dev/null
cd $(dirname $0)
echo "hello world" > test.txt
# 再次回到当前目录
popd > /dev/null
8、参数扩展的扩展形式
# 默认值/替代值:
${var:-word}:如果var不存在或为空,则返回word,但var的值不会改变。
${var:=word}:如果var不存在或为空,则将word赋值给var并返回word。
${var:+word}:如果var不为空,则返回word,否则返回空字符串。
${var:?message}:如果var不存在或为空,则显示message并退出脚本。
# 字符串长度:
${#var}:返回变量var的长度(即字符串中的字符数)。
# 子字符串提取:
${var:start:length}:从var中提取从start位置开始的长度为length的子字符串。如果省略length,则提取从start到字符串末尾的所有字符。如果start是负数,则表示从字符串末尾开始计数。
# 前缀/后缀去除:
${var#pattern}:从var的开头删除最短匹配pattern的部分。
${var##pattern}:从var的开头删除最长匹配pattern的部分。
${var%pattern}:从var的末尾删除最短匹配pattern的部分。
${var%%pattern}:从var的末尾删除最长匹配pattern的部分。
# 字符串替换:
${var/pattern/string}:将var中第一个匹配pattern的部分替换为string。
${var//pattern/string}:将var中所有匹配pattern的部分替换为string。
# 大小写转换:
${var^}:将var的第一个字母转换为大写。
${var^^}:将var中的所有字母转换为大写。
${var,}:将var的第一个字母转换为小写。
${var,,}:将var中的所有字母转换为小写。
作者:wanghongwei
版权声明:本作品遵循<CC BY-NC-ND 4.0>版权协议,商业转载请联系作者获得授权,非商业转载请附上原文出处链接及本声明。