【问题标题】:No code will run after `exec` in bash script [duplicate]bash脚本中的`exec`之后不会运行任何代码[重复]
【发布时间】:2020-03-22 01:39:39
【问题描述】:

我在命令名称中使用变量扩展进行测试的示例 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.

问题:

  1. 现在,如果我取消注释这一行:# exec "${CMD_PREFIX}ho" "hey" # works, but then prevents the code below from running!,它下面的代码将不再运行,而是得到这个输出!请注意,我不再收到 This is a test script found in ~/bin. 的 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
    
  2. 另外,它下面的eval 命令也不起作用。如果我取消注释该行,我会得到与上面发布的完全相同的错误输出,它仍然不会像应有的那样执行我对gs_test_script 的调用三次。为什么?

【问题讨论】:

标签: bash variables exec eval


【解决方案1】:

因为 exec 命令会将当前的 bash 进程替换为要执行的新命令。它不会返回调用进程。所以你不应该在你的脚本中使用 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.

【讨论】:

  • 你从哪里复制的?我在man execinfo execexec --help 中都没有看到它。
  • 对于 bash 内置,使用 help: help exec
  • help exec 的输出与上面显示的不同。也许我们有不同的版本。当我只运行help 时,顶部显示的版本是GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)。我在 Ubuntu 18.04 上。 @Changbin Du,你运行的是什么版本的 GNU bash?你从help exec 得到那个输出了吗?
  • @Gabriel:这是 bash 3.2.something,回到 2007 年,在 OS X 上可以找到(因为他们不喜欢 bash 4 及更高版本的许可)。 (是的,它来自help exec
猜你喜欢
  • 2015-02-23
  • 2017-09-30
  • 2017-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
  • 2013-08-13
相关资源
最近更新 更多