Shell学习笔记
# Shell 脚本
Shell 脚本的第一行一般是:
#!/bin/bash
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
Linux 的 Shell 种类众多,常见的有:
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
- ……
# 运行 Shell 脚本的两种方法
# 作为可执行程序
chmod +x ./test.sh # 使脚本具有执行权限
./test.sh # 执行脚本
2
注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。
# 作为解释器参数
/bin/sh ./test.sh # 执行脚本
sh ./test.sh # 执行脚本
2

# Shell 变量
https://www.runoob.com/linux/linux-shell-passing-arguments.html (opens new window)
Shell 变量名只能包含字母、数字和下划线,不能以数字开头。
变量名与等号之间不能有空格。等号两侧避免使用空格:
# 正确的赋值
variable_name=value
# 有可能会导致错误
variable_name = value
2
3
4
5
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
echo $variable_name
echo ${variable_name}
2
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界。推荐给所有变量加上花括号,避免不必要的错误,如:
for skill in Java Python Shell; do
	# 解释器会把$skillScript当成一个变量(其值为空)
    echo "I am good at $skillScript" 
    echo "I am good at ${skill}Script"
done
2
3
4
5
已定义的变量,可以被重新定义,如:
variable_name=new_value # 使用变量的时候才加美元符($)
# 字符串变量
字符串变量:使用单引号 ' 或双引号 " 来定义字符串,例如:
my_string='Hello, World!'
或者
my_string="Hello, World!"
2
3
单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的。
双引号里可以有变量,可以出现转义字符。
拼接字符串:
your_name="runoob"
# 使用双引号拼接
greeting_1="hello, "$your_name" !"
greeting_2="hello, ${your_name} !"
echo $greeting_1  $greeting_2
# 使用单引号拼接
greeting_3='hello, '$your_name' !'
greeting_4='hello, ${your_name} !' # 原样输出hello, ${your_name} !
echo $greeting_3  $greeting_4
2
3
4
5
6
7
8
9
10
获取字符串长度:
string="abcd"
echo ${#string} # 等价于 ${#string[0]}
2
# 整数变量
整数变量: 在一些Shell中,你可以使用 declare 或 typeset 命令来声明整数变量。
declare -i my_integer=42
# 数组变量
数组变量: Shell 也支持数组,允许你在一个变量中存储多个值。
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
数组名=(值1 值2 ... 值n)
例如:
array_name=(value0 value1 value2 value3)
或者:
array_name=(
value0
value1
value2
value3
)
2
3
4
5
6
整数索引数组:
my_array=(1 2 3 4 5)
Bash 支持关联数组,可以使用任意的字符串、或者整数作为下标来访问数组元素。
关联数组使用 declare 命令来声明,语法格式如下:
declare -A array_name
-A 选项就是用于声明一个关联数组。
关联数组的键是唯一的。
declare -A associative_array
associative_array["name"]="John"
associative_array["age"]=30
2
3
读取数组元素值的一般格式是:
${数组名[下标]}
例如:
valuen=${array_name[n]}
数组常用脚本:
array_name[0]=A
array_name[1]=B
array_name[2]=C
array_name[3]=D
# 获取数组中的所有元素
echo "数组的元素为: ${array_name[*]}"
echo "数组的元素为: ${array_name[@]}"
# 在数组前加一个感叹号 ! 可以获取数组的所有键,例如:
echo "数组的键为: ${!array_name[*]}"
echo "数组的键为: ${!array_name[@]}"
# 取得数组元素的个数
echo "数组元素的个数为: ${#array_name[*]}"
echo "数组元素的个数为: ${#array_name[@]}"
# 取得数组单个元素的长度
echo "第n个数组元素的长度为: ${#array_name[n]}"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 环境变量
环境变量: 这些是由操作系统或用户设置的特殊变量,用于配置 Shell 的行为和影响其执行环境。
例如,PATH 变量包含了操作系统搜索可执行文件的路径:
echo $PATH
# 特殊变量
特殊变量: 有一些特殊变量在 Shell 中具有特殊含义。例如:
| 特殊变量 | 说明 | 
|---|---|
| $0 | 脚本或函数的名称 | 
| $1...$2 | $1 表示脚本或函数的第一个参数,$2 表示脚本或函数的第二个参数,当n>=10时,需要使用${n}来获取参数。。 | 
| $# | 传递到脚本或函数的参数个数 | 
| $* | 传递给脚本或函数的全部参数。以一个单字符串显示所有传递到脚本或函数的参数 | 
| $$ | 脚本运行的当前进程ID号 | 
| $! | 后台运行的最后一个进程的ID号 | 
| $@ | 传递给脚本或函数的全部参数。 | 
| $- | 显示Shell使用的当前选项,与set命令功能相同。 | 
| $? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。在Linux shell脚本中,可以使用特殊变量$?来获取上一个命令的退出状态码(exit status code)。这个状态码是上一个命令执行后退出的时候返回的数值。一般来说,如果命令执行成功,状态码为0;如果命令执行失败,状态码非0。退出状态码是一个0到255的整数。一般来说,正数的退出状态码是由程序自己定义的,通常用于表示不同的错误类型。而负数的退出状态码通常是由于shell内部错误或者是信号导致的。在实际应用中,你应该尽量避免返回负的退出状态码,除非这是由于shell内部的特定错误。如果你的程序需要返回错误代码,应当使用0以上的正数值。 | 
| 退出码 | 解释 | 
|---|---|
| 0 | 命令成功执行 | 
| 1 | 通用错误代码 | 
| 2 | 命令(或参数)使用不当 | 
| 126 | 权限被拒绝(或)无法执行 | 
| 127 | 未找到命令,或 PATH 错误 | 
| 128+n | 命令被信号从外部终止,或遇到致命错误 | 
| 130 | 通过 Ctrl+C 或 SIGINT 终止(终止代码 2 或键盘中断) | 
| 143 | 通过 SIGTERM 终止(默认终止) | 
| 255/* | 退出码超过了 0-255 的范围,因此重新计算(LCTT 译注:超过 255 后,用退出码对 256 取模) | 
| Exit Code Number | Meaning | Example | Comments | 
|---|---|---|---|
| 1 | Catchall for general errors | var1 = 1/0 | Miscellaneous errors, such as "divide by zero" and other impermissible operations | 
| 126 | Command invoked cannot execute | /dev/null | Permission problem or command is not an executable | 
| 127 | "command not found" | illegal_command | Possible problem with $PATH or a typo | 
| 128 | Invalid argument to exit | exit 3.14159 | exit takes only integer args in the range 0 - 255 (see first footnote) | 
| 128+n | Fatal error signal "n" | kill -9 $PPID of script | $? returns 137 (128 + 9) | 
| 130 | Script terminated by Control-C | Ctl-C | Control-C is fatal error signal 2, (130 = 128 + 2, see above) | 
| 255* | Exit status out of range | exit -1 | exit takes only integer args in the range 0 - 255 | 
以下是一个简单的示例脚本,它检查最后一个命令的退出状态码,并打印出相应的消息:
#!/bin/bash
 
# 执行一个命令
ls /some/directory
 
# 检查命令的退出状态码
if [ $? -eq 0 ]; then
    echo "命令执行成功"
else
    echo "命令执行失败,退出状态码为 $?"
fi
2
3
4
5
6
7
8
9
10
11
在实际使用中,通常会直接在命令后面进行检查,而不是先执行命令,再检查$?:
#!/bin/bash
 
# 直接在命令后检查状态码
if ls /some/directory; then
    echo "命令执行成功"
else
    echo "命令执行失败,退出状态码为 $?"
fi
2
3
4
5
6
7
8
知识扩展——return和exit的使用:
- return是一个关键字; exit是一个函数。
- return是编程语言级别,它表示调用堆栈的返回;exit是系统调用级别,它表示了一个进程的结束。
- return是函数的退出(返回);exit是进程的退出,exit用于退出整个shell脚本进程。
# Shell 基本运算符
https://www.runoob.com/linux/linux-shell-basic-operators.html (opens new window)
# 算数运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
#!/bin/bash
val=`expr 2 + 2`
echo "两数之和为 : $val"
2
3
4
两点注意:
- 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
- 完整的表达式要被 `` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
# 自增和自减操作符
使用 $(( )) 进行算术运算
#!/bin/bash
# 初始化变量
num=5
# 自增
num=$((num + 1))
# 自减
num=$((num - 1))
echo $num
2
3
4
5
6
7
8
9
10
11
12
# 关系运算符(数值)
| 运算符 | 说明 | 举例 | 
|---|---|---|
| -eq | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 false。 | 
| -ne | 检测两个数是否不相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 | 
| -gt | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 | 
| -lt | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 | 
| -ge | 检测左边的数是否大于等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 | 
| -le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 | 
如果使用 ((...)) 作为判断语句,大于和小于可以直接使用 > 和 <,其他如此类推。
| 运算符 | 说明 | 举例 | 
|---|---|---|
| == | 检测两个数是否相等,相等返回 true。 | (( $a == $b )) 返回 false。 | 
| != | 检测两个数是否不相等,不相等返回 true。 | (( $a != $b )) 返回 true。 | 
| > | 检测左边的数是否大于右边的,如果是,则返回 true。 | (( $a > $b )) 返回 false。 | 
| < | 检测左边的数是否小于右边的,如果是,则返回 true。 | (( $a < $b )) 返回 true。 | 
| >= | 检测左边的数是否大于等于右边的,如果是,则返回 true。 | (( $a >= $b )) 返回 false。 | 
| <= | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | (( $a <= $b )) 返回 true。 | 
# 字符串运算符
| 运算符 | 说明 | 举例 | 
|---|---|---|
| = | 检测两个字符串是否相等,相等返回 true。 | [[ $a = $b ]] 返回 false。 | 
| != | 检测两个字符串是否不相等,不相等返回 true。 | [[ $a != $b ]] 返回 true。 | 
| -z | 检测字符串长度是否为0,为0返回 true。 | [[ -z $a ]] 返回 false。 | 
| -n | 检测字符串长度是否不为 0,不为 0 返回 true。 | [[ -n "$a" ]] 返回 true。 | 
| $ | 检测字符串是否不为空,不为空返回 true。 | [[ $a ]] 返回 true。 | 
# 文件测试运算符
| 操作符 | 说明 | 举例 | 
|---|---|---|
| -b file | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 | 
| -c file | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] 返回 false。 | 
| -d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false。 | 
| -f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 | 
| -g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 | 
| -k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 | 
| -p file | 检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 | 
| -u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 | 
| -r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true。 | 
| -w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 | 
| -x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 | 
| -s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 | 
| -e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 | 
| -S file | 判断某文件是否 socket。 | |
| -L file | 检测文件是否存在并且是一个符号链接。 | 
# 布尔运算符
| 运算符 | 说明 | 举例 | 
|---|---|---|
| ! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 | 
| -o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 | 
| -a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 | 
# 逻辑运算符
| 运算符 | 说明 | 举例 | 
|---|---|---|
| && | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false | 
| || | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true | 
# Shell test 命令
Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
在Shell脚本中,test命令和[](方括号表达式)都用于条件测试,但它们在使用上有一些区别。
- test命令:这是一个独立的命令,用于测试条件表达式的值,并根据测试结果返回0(真)或非0值(假)。例如,test -f file.txt会检查file.txt是否存在并且是一个普通文件。如果条件为真,则返回0;否则返回非0值。
- 方括号表达式:[ ]用于在脚本中进行条件测试,它实际上是一个命令替换的语法,可以与逻辑运算符一起使用。例如,[ -f file.txt ]与test -f file.txt是等价的。方括号表达式也返回0或非0值,表示条件的真假。
在Shell脚本中,test命令和[]通常可以互换使用,但有一些细微的差别。例如,当使用逻辑运算符如&&和||时,[]不支持旧式的-a和-o运算符,而推荐使用&&和||。此外,对于模式匹配和正则表达式匹配,通常使用[[ ]](双左方括号),而基本的条件测试则可以使用[ ]或test命令。
总的来说,虽然test命令和[]在功能上是相似的,但它们的使用场景和语法有所不同。在编写Shell脚本时,应根据具体的需求和上下文选择合适的方法进行条件测试。
# Shell 括号的用法
在Shell中,括号有小括号、中括号和大括号。每种括号都有其特定的用途和语法规则。
- 小括号: - 单小括号: - 用于命令替换。例如, - echo $(ls)会执行- ls命令,并将输出作为- echo命令的参数,等同于- echo `ls`。
- 用于命令组合和执行,可以创建一个子shell来顺序执行命令。例如, - (pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls)会创建一个子shell并执行其中的命令。
- 用于初始化数组。例如, - array=(a b c d)会创建一个包含元素a、b、c、d的数组。
 
- 双小括号: - 用于算术运算和比较。((表达式))常用于算术运算比较,双括号中的变量可以不使用$符号前缀。 - #!/bin/bash #求100以内的偶数 num=2 while ((num<100)) #数值与运算符可以没有空格,变量的使用时也可以不使用$num do echo "$num" ((num=num*2)) done1
 2
 3
 4
 5
 6
 7
 8
- 用于循环语句。例如, - for((i=0;i<5;i++))可以在双小括号内进行循环变量的递增。
 
 
- 中括号: - 单中括号: - 用于条件表达式,算术比较,例如,[ $i -ge 1 ]进行数值比较。
- 用于条件表达式,文件测试,例如,[ -d $file ]检测文件是否是目录。
- 字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。例如,cat 1.txt|grep "[0-9]"。
- 引用数组中每个元素。例如,${array_name[2]}。
 
- 用于条件表达式,算术比较,例如,
- 双中括号: - 用于条件表达式,字符串比较,例如,[[ hello == hell? ]]进行字符串模式匹配和正则表达式匹配。在进行字符串比较时,最好使用双中括号 [[ ]]. 因为单中括号可能会导致一些错误,因此最好避开它们。
 
- 用于条件表达式,字符串比较,例如,
 
- 大括号: - 帮助解释器识别变量的边界。
- 用于变量替换,如 ${var:-string}当变量为空时,将string赋值给var。
- 在序列生成中,如 {1..4}用于生成数字序列。
- 用于文件名扩展,如 {1,4}.txt可以生成1.txt和4.txt两个文件,cp /path/to/file.txt{,.backup}可以在/path/to目录下生成备份文件file.txt.backup。
 
在Shell脚本中,单中括号[ ]和双中括号[[ ]]各有其用途,选择使用哪种括号取决于特定的需求和场景。
- 单中括号[ ]:- 主要用于测试条件表达式的返回值,它是一个测试命令,返回0表示真,非0表示假。
- 在进行算术比较或算术运算时,单中括号[ ]更为合适。例如,进行数值比较或执行算术运算时,应使用单中括号。
- 单中括号内的表达式需要特别注意空格的使用,例如[ $a -eq $b ],缺少空格可能会导致错误。
 
- 双中括号[[ ]]:- 提供了更强大的字符串处理能力,支持模式匹配和正则表达式,对于字符串和文件名的处理更为灵活。
- 双中括号在条件判断时可以不用引号包围变量,也可以支持逻辑操作符&&、||,并且不需要转义字符。
- 双中括号在语法上更接近于其他编程语言,提供了一定的编程便利性。
 
总结来说,当需要进行算术比较或运算时,应使用单中括号[ ];而当需要进行字符串处理、模式匹配或提供更友好的语法时,应使用双中括号[[ ]]。在实际应用中,根据具体的需求选择合适的括号可以提高脚本的健壮性和可读性。
# Shell 流程控制
# 条件结构
if 语法格式:
if condition
then
    command1 
    command2
    ...
    commandN 
fi
# 写成一行
if condition; then command1; command2… fi
2
3
4
5
6
7
8
9
10
if else 语法格式:
if condition
then
    command1 
    command2
    ...
    commandN
else
    command
fi
2
3
4
5
6
7
8
9
if else-if else 语法格式:
if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi
2
3
4
5
6
7
8
9
case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。
可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
case ... esac 语法格式:
case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac
2
3
4
5
6
7
8
9
10
11
12
13
14
# 循环结构
for 语法格式:
for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done
# 写成一行
for var in item1 item2 ... itemN; do command1; command2… done;
# 无限循环语法格式
for (( ; ; ))
do
    command
done
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
while 语法格式:
while condition
do
    command
done
# 无限循环语法格式一
while :
do
    command
done
# 无限循环语法格式二
while true
do
    command
done
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
until 语法格式:
until condition
do
    command
done
2
3
4
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:break 和 continue。
break 命令允许跳出所有循环(终止执行后面的所有循环)。
continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
# Shell 函数
Shell 函数定义语法格式:
[ function ] funname [()]
{
    action;
    [return int;]
}
2
3
4
5
说明:
- 可以带 function fun() 定义,也可以直接 fun() 定义,不带任何参数。
- 所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。
- 在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
- 函数返回值,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return 语句只能返回一个介于 0 到 255 之间的整数。
- 函数返回值在调用该函数后通过 $? 来获得。
# Shell 命令连接
在Shell中,命令连接可以使用多种符号,常见的有以下几种:
| 类型 | 符号 | 说明 | 
|---|---|---|
| 分号 | ; | 无论前一个命令执行成功与否,都会执行下一条命令。 | 
| & | 多个命令同时执行,不管命令是否执行成功。 | |
| 逻辑与 | && | 只有前一个命令执行成功时,才会执行下一条命令。 | 
| 逻辑或 | || | 只有前一个命令执行失败时,才会执行下一条命令。 | 
| 管道 | | | 将前一个命令的输出作为后一个命令的输入。 | 
# 标准输入/输出和重定向
执行一个shell命令行,系统有三个默认的文件描述符供程序使用。标准输入文件(STDIN),通常对应终端的键盘;标准输出文件(STDOUT)和标准错误输出文件(STDERR),这两个文件都对应终端的屏幕。
使用符合 “>” 将屏幕的输出导入到文件,屏幕不再有显示,“>” 会覆盖之前的内容。
使用符合 “>>” 将屏幕的输出追加到文件,屏幕不再有显示,“>>” 不会覆盖之前的内容。
标准输入用“0”表示。
标准正确输出用 “1” 表示。“1”可以省略。>file等同于1>file,>>file等同于1>>file
标准错误输出用 “2” 表示。
| 类型 | 操作符 | 用途 | 
|---|---|---|
| 重定向输入 | < | 从指定的文件读取数据,而不是从键盘输入 | 
| 重定向输出 | > | 将输出结果保存到指定的文件(覆盖原有内容) | 
| 重定向输出 | >> | 将输出结果追加到指定的文件尾部 | 
| 标准错误输出 | 2> | 将错误信息保存到指定的文件(覆盖原有内容) | 
| 标准错误输出 | 2>> | 将错误信息追加到指定的文件尾部 | 
| 混合输出 | &> | 将标准正确输出、标准错误输出的内容保存到同一文件(覆盖原有内容) | 
| 混合输出 | &>> | 将标准正确输出、标准错误输出的内容追加到指定的文件尾部 | 
nohup command >/dev/null 2>&1 &
nohup 英文全称 no hang up(不挂起),用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行。
nohup 命令,在默认情况下(非重定向时),会输出一个名叫 nohup.out 的文件到当前目录下,如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。
nohup 命令语法格式:
nohup command [arg...] &
命令 /dev/null 2>&1 & 的主要作用是将程序的标准输出和错误输出都重定向到 /dev/null,从而屏蔽这些输出,使得运行该命令的用户不会看到任何输出信息。
这个命令组合可以分解为几个部分来理解:
- /dev/null代表空设备文件,是一个特殊的文件,所有写入它的内容都会被永久丢弃,因此被称为“黑洞”或“垃圾桶”。
- >/dev/null等同于- 1>/dev/null,将标准错误输出保存到空设备文件。
- 2>&1是一个shell重定向技巧,它将标准错误输出(文件描述符2)重定向到标准输出(文件描述符1)当前指向的位置。在这个上下文中,由于标准输出也被重定向到了- /dev/null,因此标准错误输出也随之被丢弃。
- &在命令的末尾表示将命令放到后台执行,这样用户可以在不等待命令执行完成的情况下继续使用终端。
# 参考资料
https://www.runoob.com/linux/linux-shell.html (opens new window)
