在 bash 脚本中的 `exec` 之后没有代码会 运行
No code will run after `exec` in bash script
示例 bash 脚本,我在其中使用命令名称中的变量扩展进行测试:
test_command_w_variable_expansion_in_name.sh:
#!/bin/bash
# Gabriel Staples
# 21 Mar. 2020
echo "PATH = \"$PATH\""
# PATH="$HOME/bin:$PATH"
# echo "PATH = \"$PATH\""
# 1st, create a command in ~/bin to test here
mkdir -p ~/bin
echo -e "#!/bin/bash\necho \"This is a test script found in ~/bin.\"" > ~/bin/gs_test_script
chmod +x ~/bin/gs_test_script
# 1)
# command: `echo`
CMD_PREFIX="ec"
${CMD_PREFIX}ho "hey" # works
# exec "${CMD_PREFIX}ho" "hey" # works, but then prevents the code below from running!
# eval "${CMD_PREFIX}ho" "hey" # does NOT work, but also throws no error
# 2)
# command: `gs_test_script` from ~/bin
CMD_PREFIX="gs_test"
~/bin/gs_test_script # works!
gs_test_script # works!
${CMD_PREFIX}_script # works!
输出:
$ ./test_command_w_variable_expansion_in_name.sh
PATH = "/home/gabriel/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
hey
This is a test script found in ~/bin.
This is a test script found in ~/bin.
This is a test script found in ~/bin.
问题:
现在,如果我取消注释这一行:# exec "${CMD_PREFIX}ho" "hey" # works, but then prevents the code below from running!
,它下面的代码将不再运行,而是我得到这个输出!请注意,我不再获得 This is a test script found in ~/bin.
Why?
的 3 个打印输出
$ ./test_command_w_variable_expansion_in_name.sh
PATH = "/home/gabriel/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
hey
hey
此外,它下面的eval
命令不起作用。如果我取消注释该行,我会得到与上面发布的完全相同的错误输出,它仍然没有像应该的那样执行我对 gs_test_script
的调用三次。为什么?
因为exec命令会将当前的bash进程替换为要执行的新命令。它不会 return 调用进程。所以你不应该在你的脚本中使用 exec。
exec [-cl] [-a name] [command [arguments]]
If command is specified, it replaces the shell. No new process
is created. The arguments become the arguments to command. If
the -l option is supplied, the shell places a dash at the
beginning of the zeroth argument passed to command. This is
what login(1) does. The -c option causes command to be executed
with an empty environment. If -a is supplied, the shell passes
name as the zeroth argument to the executed command. If command
cannot be executed for some reason, a non-interactive shell
exits, unless the execfail shell option is enabled. In that
case, it returns failure. An interactive shell returns failure
if the file cannot be executed. If command is not specified,
any redirections take effect in the current shell, and the
return status is 0. If there is a redirection error, the return
status is 1.
示例 bash 脚本,我在其中使用命令名称中的变量扩展进行测试:
test_command_w_variable_expansion_in_name.sh:
#!/bin/bash
# Gabriel Staples
# 21 Mar. 2020
echo "PATH = \"$PATH\""
# PATH="$HOME/bin:$PATH"
# echo "PATH = \"$PATH\""
# 1st, create a command in ~/bin to test here
mkdir -p ~/bin
echo -e "#!/bin/bash\necho \"This is a test script found in ~/bin.\"" > ~/bin/gs_test_script
chmod +x ~/bin/gs_test_script
# 1)
# command: `echo`
CMD_PREFIX="ec"
${CMD_PREFIX}ho "hey" # works
# exec "${CMD_PREFIX}ho" "hey" # works, but then prevents the code below from running!
# eval "${CMD_PREFIX}ho" "hey" # does NOT work, but also throws no error
# 2)
# command: `gs_test_script` from ~/bin
CMD_PREFIX="gs_test"
~/bin/gs_test_script # works!
gs_test_script # works!
${CMD_PREFIX}_script # works!
输出:
$ ./test_command_w_variable_expansion_in_name.sh
PATH = "/home/gabriel/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
hey
This is a test script found in ~/bin.
This is a test script found in ~/bin.
This is a test script found in ~/bin.
问题:
现在,如果我取消注释这一行:
的 3 个打印输出# exec "${CMD_PREFIX}ho" "hey" # works, but then prevents the code below from running!
,它下面的代码将不再运行,而是我得到这个输出!请注意,我不再获得This is a test script found in ~/bin.
Why?$ ./test_command_w_variable_expansion_in_name.sh PATH = "/home/gabriel/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" hey hey
此外,它下面的
eval
命令不起作用。如果我取消注释该行,我会得到与上面发布的完全相同的错误输出,它仍然没有像应该的那样执行我对gs_test_script
的调用三次。为什么?
因为exec命令会将当前的bash进程替换为要执行的新命令。它不会 return 调用进程。所以你不应该在你的脚本中使用 exec。
exec [-cl] [-a name] [command [arguments]] If command is specified, it replaces the shell. No new process is created. The arguments become the arguments to command. If the -l option is supplied, the shell places a dash at the beginning of the zeroth argument passed to command. This is what login(1) does. The -c option causes command to be executed with an empty environment. If -a is supplied, the shell passes name as the zeroth argument to the executed command. If command cannot be executed for some reason, a non-interactive shell exits, unless the execfail shell option is enabled. In that case, it returns failure. An interactive shell returns failure if the file cannot be executed. If command is not specified, any redirections take effect in the current shell, and the return status is 0. If there is a redirection error, the return status is 1.