看shell脚本的时候,发现两个奇怪的用法 $@
和 $?
sh run_task.python $@
RETURN_VALUE=$?
if [ ${RETURN_VALUE} -ne 0 ]; then
echo "xx.sh job error!"
exit 1
fi
1. 来看 $@
$@
是一个特殊的 shell 变量,在 shell 脚本中用来表示所有传递给脚本的命令行参数。当在一个脚本中使用 $@
,它会展开成调用该脚本时传递的所有参数,每个参数作为独立的字符串。
例如,假设有一个名为 wrapper_script.sh
的脚本,内容如下:
#!/bin/bash
# wrapper_script.sh
# 调用另一个脚本,并将所有传递给本脚本的参数传递给那个脚本
sh run_task.python $@
如果运行这个 wrapper_script.sh
并传递一些参数:
./wrapper_script.sh arg1 arg2 arg3
那么 wrapper_script.sh
会执行 run_task.python
脚本,并将 arg1
、arg2
和 arg3
作为参数传递给它,就像你直接运行了以下命令:
sh run_task.python arg1 arg2 arg3
$@
确保了所有传递给 wrapper_script.sh
的参数都被原封不动地传递给 run_task.python
脚本。
在编写需要传递参数的脚本时,$@
是非常有用的,因为它允许脚本灵活地处理任意数量的参数,并将这些参数传递给其他命令或脚本。
2. 来看 $*
简单来说,$*
允许你将所有传递给 shell 脚本或函数的参数“传递”给另一个命令,与$@
用法类似
但是,需要注意的是,在某些情况下,使用 $@
而不是 $*
可能更为合适,因为 $@
会保留每个参数的引号,从而能够正确处理包含空格的参数。而 $*
会将所有参数视为一个单一的字符串,参数之间用空格分隔,这可能导致意外的行为。
例如,如果你有一个参数 "my file.txt"
(注意这是一个带有空格的单一参数),使用 $*
可能会将其拆分为两个参数 my
和 file.txt
,而 $@
则会将其保留为一个完整的参数。
3. 来看 $?
$?
是一个特殊的变量,代表上一个命令执行的退出状态码(exit status)。退出状态码是一个数字,通常用于表示命令执行的成功与否。按照惯例:
如果 $?
返回 0
,表示上一个命令执行成功。
如果 $?
返回非 0 值,表示上一个命令执行失败或遇到错误。具体的非零值可以提供关于错误类型的额外信息。
在最上面的脚本中
RETURN_VALUE=$?
这行代码将上一个命令的退出状态码赋值给变量 RETURN_VALUE
。这样,你就可以在后续的脚本中使用这个变量来检查之前的命令是否执行成功,或者根据退出状态码来执行不同的操作。
看个例子:
#!/bin/bash
# 尝试复制一个文件
cp source.txt destination.txt
# 捕获退出状态码
RETURN_VALUE=$?
# 根据退出状态码判断命令是否执行成功
if [ $RETURN_VALUE -eq 0 ]; then
echo "File copied successfully."
else
echo "Error occurred while copying the file."
fi
在这个脚本中,cp
命令用于复制文件。如果复制成功,$?
将返回 0
,否则返回非 0
值。然后,脚本使用 RETURN_VALUE
变量来存储这个退出状态码,并根据其值输出相应的消息。
4. 来看 $#
在Shell脚本中,$#
是一个特殊变量,用于表示传递给脚本或函数的参数个数。
例如,如果你有一个名为 script.sh
的Shell脚本,内容如下:
#!/bin/bash
echo "The number of arguments is: $#"
当你以不同的参数运行这个脚本时,它会输出传递给它的参数个数:
$ ./script.sh arg1 arg2 arg3
The number of arguments is: 3
在这个例子中,$#
的值是3
,因为脚本接收到了3
个参数(arg1, arg2, 和 arg3)。
5. 来看 set -x
set -x 是一个 Bash shell 的内建命令,用于开启调试模式。当你在脚本中使用 set -x 后,Bash 会打印出执行的每一条命令,以及在执行该命令之前将其展开。这有助于开发者理解脚本在执行时的具体行为,特别是当脚本中的变量被替换为实际值时。
例如,考虑以下脚本:
#!/bin/bash
set -x
VAR="Hello, World!"
echo $VAR
当你运行这个脚本时,你会在输出中看到类似以下内容:
+ VAR='Hello, World!'
+ echo 'Hello, World!'
Hello, World!
这里,+ VAR='Hello, World!'
和 + echo 'Hello, World!'
是由于 set -x
而打印出来的调试信息,显示了实际执行的命令。