查找可执行文件时bash的奇怪行为

时间:2015-07-10 15:40:10

标签: macos bash python-3.x osx-mavericks

我正在开发一个内部必须调用ninja命令的Python应用程序,但它无法找到subprocess模块的可执行文件。当我通过shell=True时,确实找到了可执行文件,但是没有将参数传递给进程。使用os.system()工作。

subprocess.call(['ninja'] + args)              # Can't find ninja
subprocess.call(['ninja'] + args, shell=True)  # Finds & runs ninja, but the additional arguments int "args" are not passed
os.system(' '.join(shlex.quote(x) for x in ['ninja'] + args))  # Works fine

当我检查ninjabash的位置时,事情开始对我来说很奇怪。

$ which ninja
$ type ninja
ninja is hashed (/Users/niklas/Bin/ninja)
$ echo $PATH
~/Bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/texbin:/Library/Frameworks/Python.framework/Versions/3.4/bin/:/Users/niklas/Documents/apache-maven-3.3.3/bin:/Users/niklas/Documents/grib2json-0.8.0-SNAPSHOT/bin
  1. which无法找到ninja
  2. type ninja让它位于/Users/niklas/Bin/ninja
  3. 路径/Users/niklas/Bin不在$PATH
  4. 我的设置出了什么问题?为什么bash实际上可以找到ninja,但只能在shell=True模式下找到Python,然后为什么没有传递额外的参数呢?

2 个答案:

答案 0 :(得分:3)

问题是var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com"); var numberAuthToken = 212312312312312; // number var stringAuthToken = String(numberAuthToken); ref.authWithCustomToken(stringAuthToken, function(error, authData) { if (error) { console.log("Authentication Failed!", error); } else { console.log("Authenticated successfully with payload:", authData); } }); 是一种基础,而python正在调用os.execvp()来执行subprocess.call(),这显然是使用execvp(),系统调用,其中不做波浪扩展

您的PATH应为~。当您设置/Users/niklas/Bin:...时,波浪线扩展通常由shell完成。

所以bash可以找到它,因为它每次重新进行波浪扩展,但execvp()永远不会找到它。

正如@larsks所说,PATH=~/Bin:$PATH需要一个字符串。

答案 1 :(得分:1)

如果您要设置shell=True,那么您的命令必须是字符串而不是列表。考虑:

>>> import subprocess
>>> subprocess.call(['echo', 'hello'], shell=True)

0
>>> subprocess.call('echo hello', shell=True)
hello
0

如果您使用shell=True传递列表,则只会考虑列表的第一项:

>>> subprocess.call(['echo hello', 'hello'], shell=True)
hello
0
>>> 
  

路径/ Users / niklas / Bin不在$ PATH

是的。这是第一个项目:

$ echo $PATH
~/Bin:/usr/local/bin:...

...假设您是niklas