Shell 中编写的函数,如果函数名中带了中横线,在使用 /bin/sh
执行时会报错。
➜ subprocess git:(master) ✗ cat kubectl.sh
_kubectl_api-resources()
{
hostname
}
_kubectl_api-resources
➜ subprocess git:(master) ✗ sh kubectl.sh
kubectl.sh: line 5: `_kubectl_api-resources': not a valid identifier
根据 POSIX 的标准,函数名要符合以下的规范。
3.231 Name
In the shell command language, a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit.
可以看到,中横线不在标准支持的范围内。因此使用 /bin/sh
执行时,会看到我们上面列出的错误。
但是 bash
和 zsh
却可以支持函数中的中横线。
➜ subprocess git:(master) ✗ cat kubectl.sh
_kubectl_api-resources()
{
hostname
}
_kubectl_api-resources
➜ subprocess git:(master) ✗ sh kubectl.sh
kubectl.sh: line 5: `_kubectl_api-resources': not a valid identifier
➜ subprocess git:(master) ✗ bash kubectl.sh
bogon
➜ subprocess git:(master) ✗ zsh kubectl.sh
bogon
因此,如果我们希望我们的 Shell 脚本具有更好的可移植性,那就尽量避免在函数命名时使用中横线。
Python 使用 subprocess.Popen 执行 shell 时,若选择了 shell=True
选项,则会默认使用 /bin/sh
。因此在遇到使用了中横线的 shell 函数时,也会报错。如果希望使用 /bin/bash
则需要设置 executable
参数,示例如下:
import subprocess
def bash_command(cmd):
subprocess.Popen(cmd, shell=True, executable='/bin/bash')
bash_command('a="Apples and oranges" && echo "${a/oranges/grapes}"')
如果这个方法不生效,还可以使用下面的方案。
import subprocess
def bash_command(cmd):
subprocess.Popen(['/bin/bash', '-c', cmd])