zsh如何解释shebangs中的非绝对路径?(WAS:为什么python3-i允许在shebang中使用非绝对路径?)

zsh如何解释shebangs中的非绝对路径?(WAS:为什么python3-i允许在shebang中使用非绝对路径?),zsh,shebang,Zsh,Shebang,我最近发现了Python的-I参数,它在脚本完成后运行。相当整洁 $ cat test.py #!python3 -i x=5 print('The value of x is ' + str(x)) $ ./test.py The value of x is 5 >>> print(str(x+1)) 6 >>> zsh: suspended ./test.py 但是,当我尝试将此脚本复制到在完成时终止的版本时,它失败了: $ cat test1.p

我最近发现了Python的
-I
参数,它在脚本完成后运行。相当整洁

$ cat test.py
#!python3 -i

x=5
print('The value of x is ' + str(x))
$ ./test.py
The value of x is 5
>>> print(str(x+1))
6
>>> 
zsh: suspended  ./test.py
但是,当我尝试将此脚本复制到在完成时终止的版本时,它失败了:

$ cat test1.py
#!python3

x=5
print('The value of x is ' + str(x))
$ ./test.py
/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python: can't open file '
x=5
print('The value of x is ' + str(x))
': [Errno 2] No such file or directory
从一些人那里,我发现我原来犯了一个错误,
#/usr/bin/env python3
是正确的shebang

然而,我很好奇为什么只有当我给出
-I
标志时,
python3
的非绝对路径才会成功。我想这一定与
zsh
如何解释非绝对shebangs有关,但我不知道如何对此进行调查

系统设置:MacOS 10.12.6、iTerm2 3.1.6、zsh 5.2
python3
给出的
/usr/local/bin/python3
,该目录位于
$PATH

有趣的是,我在sh上没有得到相同的行为:

$ sh
sh-3.2$ cat test.py
#!python3

x=5
print('The value of x is ' + str(x))
sh-3.2$ ./test.py
sh: ./test.py: python3: bad interpreter: No such file or directory

我收到一些评论,认为这与CWD或权限有关<代码>Python 3不在我的CWD中,并且两个文件都具有执行权限:

$ ls -al | grep 'py' | awk '{print $1, $10}'
-rw------- .python_history
-rwxr-xr-x test.py
-rwxr-xr-x test1.py

除非解释器被激活,否则内核不会执行脚本

  • 指定为绝对路径,或
  • 指定为相对于当前工作目录的路径
然后,如果内核拒绝执行脚本,您的shell可能会接管并尝试执行它,根据它自己的规则解释shebang行(例如在
$PATH
中查找可执行文件)

zsh
确实尝试这样做<代码>sh没有

然而
zsh
解释shebang(可能还有后面的行)的方式真的很奇怪。看起来它总是希望在命令名之后有一个参数。看看它能做什么:

$ cat test.py 
#!python3 -b -i 

x=5
print('The value of x is ' + str(x))
$ strace -f -e execve zsh
execve("/bin/zsh", ["zsh"], 0x7ffd35c9e198 /* 78 vars */) = 0
host% ./test.py 
strace: Process 5510 attached
[pid  5510] execve("./test.py", ["./test.py"], 0x558ec6e46710 /* 79 vars */) = -1 ENOENT (No such file or directory)
[pid  5510] execve("/usr/bin/python3", ["python3", "-b -i", "./test.py"], 0x558ec6e46710 /* 79 vars */) = 0
[pid  5510] execve("/usr/lib/python-exec/python3.4/python3", ["/usr/lib/python-exec/python3.4/p"..., "-b -i", "./test.py"], 0x7fffd30eb208 /* 79 vars */) = 0
Unknown option: - 
usage: /usr/lib/python-exec/python3.4/python3 [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.
[pid  5510] +++ exited with 2 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=5510, si_uid=1000, si_status=2, si_utime=0, si_stime=0} ---
host% 
+++ exited with 2 +++
看看
[“python3”、“-b-i”、“/test.py”]
是如何作为参数传递的。我觉得把这两个开关
-b
-i
放在一起似乎很违反直觉,但zsh就是这么做的。Python显然不理解这一点

当没有参数时,确切的行为取决于程序名后是否有空格,但在这两种情况下都很奇怪。你自己检查一下,因为你不会相信我


据我所知,shebang行的zsh处理只是有缺陷。

Python与此无关。你的壳对shebang负责。好吧,很公平-那么,让我重新表述我的问题。“为什么zsh的行为方式会导致python3的非绝对路径有时能如预期的那样工作,而其他路径却不能?”您没有正确地进行实验。请在不更改当前工作目录的情况下重试。Shebang(1)使用绝对路径,(2)使用相对于CWD的路径<代码>$PATH或命令行参数在其中不起作用。但我不知道test1是怎么回事。没有执行权限?对不起,我说得不准确,请参阅我的答案以了解详细信息。