我想使用Python脚本在我的zsh上安装,所以我从github进行无人值守安装。它使用sh -c
下载安装脚本并使用sh:执行它
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
我想用subprocess
在python
中完成,所以我写了这个:
args = [
"sh",
"-c",
"$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
"",
"--unattended"
]
p = subprocess.run(args, check=True)
然而,我得到了错误,它说:
sh 1: #!/bin/sh: Not such file or directory
我想这意味着sh将shebang行解释为命令。它是如何发生的,如何避免?非常感谢!!!!
您的命令实际执行的操作;
- 它在当前shell中运行
curl
- 然后它将引用的输出从
curl
传递到sh -c
也就是说,双引号内的字符串是curl
已经获取的脚本文本。
Python代码实际所做的是不同的。
我会把它重构成
import requests
import subprocess
r = requests.get('https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh')
subprocess.run(['sh'], input=r.text, text=True)
或者,更确切地说,复制现有的命令,
subprocess.run(['sh', '-c', r.text, '', '--unattended'])
(如果您不想引入第三方库,requests
在这里不是绝对必要的。
from urllib3 import PoolManager as u3
r = u3().request('GET', 'https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh')
subprocess.run(['sh', '-c', r.data, '', '--unattended'])
但正如您所看到的,只使用Python标准库有点麻烦。(
问题是您需要两轮评估:一轮是扩展命令替换,第二轮是将其视为shell代码。如果您在shell命令中使用了单引号,您也会看到同样的问题。
您可以显式添加eval
:
args = [
"sh",
"-c",
"eval "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)""
"",
"--unattended"
]
p = subprocess.run(args, check=True)