grep envoy.run 没有这样的文件或目录
grep No such file or directory with envoy.run
我尝试构建脚本,在我的日志中执行一些 grep 搜索并打印结果。
我尝试使用 Envoy,因为它比 subprocess 更容易,但是当我执行 grep 命令时,它给我返回一个错误,没有这样的文件 o 目录。
目录结构很简单:
- 。 # 脚本根目录
- test.py#脚本文件
- web_logs/log/ # 包含要搜索的日志的目录
我的test.py很简单:
import envoy
def test(value):
search = "grep 'cv="+str(value)+"' ./web_logs/log/log_*"
print(search) #check of the search string
r = envoy.run(search)
print(r.status_code, r.std_out, r.std_err)#check of the command
response = r.std_out
if __name__ == "__main__":
test(2)
输出为:
grep 'cv=2' ./web_logs/log/log_*
(2, '', 'grep: ./web_logs/log/log_*: No such file or directory\n')
如果我运行同样的命令:
grep 'cv=2' ./web_logs/log/log_*
我可以在日志文件中找到字符串 "cv=2"。
哪里出错了?
回答后更新
问题在于使用*,如果不使用 glob 模块,envoy 无法爆炸,所以我按原样使用子进程,我尝试更好地研究使用 glob 模块来改进 envoy。
我使用的新代码是:
import subprocess
def test(value):
search = "grep 'cv="+str(value)+"' ./web_logs/log/log_*"
print(search) #check of the search string
proc = subprocess.check_output(search, shell=True)
print proc.split('\n')
if __name__ == "__main__":
test(2)
为什么它在终端中有效但在特使中无效与 globbing (bash example) 有关。
当你 运行 在你的终端
grep 'cv=2' ./web_logs/log/log_*
bash 将解析命令行并用每次匹配的文件替换星号。所以如果你有 ./web_logs/log/log_1
./web_logs/log/log_2
和 ./web_logs/log/log_foo
你的命令实际上是
grep 'cv=2' ./web_logs/log/log_1 ./web_logs/log/log_2 ./web_logs/log/log_foo
当你在 envoy 中执行同样的事情时,那是不同的,它不会执行文件的 globing 然后它会传递给 grep 一个名为 ./web_logs/log/log_*
的文件,该文件不存在,您在问题中粘贴的行实际上证实了这一点。
print r.std_err
'grep: ./web_logs/log/log_*: No such file or directory\n'
ps:python
有一个glob module
@baptistemm 实际上是正确的,因为你没有 运行ning bash 作为你过程的一部分,通配符不起作用。
然而,发生的事情更深层次。
当您 运行 一个子进程时,它可以由多个系统服务(系统调用)之一完成。
简答(TLDR;)
正确的做法是:
import envoy
def test(value):
search = "/bin/sh -c \"grep 'cv="+str(value)+"' ./web_logs/log/log_*\""
print(search) #check of the search string
r = envoy.run(search)
print(r.status_code, r.std_out, r.std_err)#check of the command
response = r.std_out
if __name__ == "__main__":
test(2)
运行 作为 shell 命令的命令将负责 globbing。
长答案
每当执行一个子进程时,它最终都会被翻译成一个 execve 系统调用(或等效的)。
在 C
库中有辅助函数,例如 system(3)
和 popen(3)
,它们环绕 execve(2)
以提供更简单的执行流程的方法。 system
启动一个 shell 并将其参数按原样传递给 shell 的 -c
选项。 popen 有额外的魔力,有点像 envoy 在 python.
中所做的
在 envoy 中,参数在 envoy 代码中被解析为 |
(参见 def expand_args(command):
)。然后使用 popen
的等价物来执行进程。 envoy
本质上是 shell 对 |
标记所做的(将内容拆分到 |
然后使用 popen)。
envoy 没有做的是像 shell 那样解释 *
,就像使用某种 glob
函数扩展它以匹配文件一样。 Bash 确实如此。这就是我的答案。
一个有趣的练习是你向 envoy 贡献代码 :-) 并让它进行 globbing。
我尝试构建脚本,在我的日志中执行一些 grep 搜索并打印结果。 我尝试使用 Envoy,因为它比 subprocess 更容易,但是当我执行 grep 命令时,它给我返回一个错误,没有这样的文件 o 目录。
目录结构很简单:
- 。 # 脚本根目录
- test.py#脚本文件
- web_logs/log/ # 包含要搜索的日志的目录
我的test.py很简单:
import envoy
def test(value):
search = "grep 'cv="+str(value)+"' ./web_logs/log/log_*"
print(search) #check of the search string
r = envoy.run(search)
print(r.status_code, r.std_out, r.std_err)#check of the command
response = r.std_out
if __name__ == "__main__":
test(2)
输出为:
grep 'cv=2' ./web_logs/log/log_*
(2, '', 'grep: ./web_logs/log/log_*: No such file or directory\n')
如果我运行同样的命令:
grep 'cv=2' ./web_logs/log/log_*
我可以在日志文件中找到字符串 "cv=2"。
哪里出错了?
回答后更新 问题在于使用*,如果不使用 glob 模块,envoy 无法爆炸,所以我按原样使用子进程,我尝试更好地研究使用 glob 模块来改进 envoy。
我使用的新代码是:
import subprocess
def test(value):
search = "grep 'cv="+str(value)+"' ./web_logs/log/log_*"
print(search) #check of the search string
proc = subprocess.check_output(search, shell=True)
print proc.split('\n')
if __name__ == "__main__":
test(2)
为什么它在终端中有效但在特使中无效与 globbing (bash example) 有关。
当你 运行 在你的终端
grep 'cv=2' ./web_logs/log/log_*
bash 将解析命令行并用每次匹配的文件替换星号。所以如果你有 ./web_logs/log/log_1
./web_logs/log/log_2
和 ./web_logs/log/log_foo
你的命令实际上是
grep 'cv=2' ./web_logs/log/log_1 ./web_logs/log/log_2 ./web_logs/log/log_foo
当你在 envoy 中执行同样的事情时,那是不同的,它不会执行文件的 globing 然后它会传递给 grep 一个名为 ./web_logs/log/log_*
的文件,该文件不存在,您在问题中粘贴的行实际上证实了这一点。
print r.std_err
'grep: ./web_logs/log/log_*: No such file or directory\n'
ps:python
有一个glob module@baptistemm 实际上是正确的,因为你没有 运行ning bash 作为你过程的一部分,通配符不起作用。
然而,发生的事情更深层次。
当您 运行 一个子进程时,它可以由多个系统服务(系统调用)之一完成。
简答(TLDR;)
正确的做法是:
import envoy
def test(value):
search = "/bin/sh -c \"grep 'cv="+str(value)+"' ./web_logs/log/log_*\""
print(search) #check of the search string
r = envoy.run(search)
print(r.status_code, r.std_out, r.std_err)#check of the command
response = r.std_out
if __name__ == "__main__":
test(2)
运行 作为 shell 命令的命令将负责 globbing。
长答案
每当执行一个子进程时,它最终都会被翻译成一个 execve 系统调用(或等效的)。
在 C
库中有辅助函数,例如 system(3)
和 popen(3)
,它们环绕 execve(2)
以提供更简单的执行流程的方法。 system
启动一个 shell 并将其参数按原样传递给 shell 的 -c
选项。 popen 有额外的魔力,有点像 envoy 在 python.
在 envoy 中,参数在 envoy 代码中被解析为 |
(参见 def expand_args(command):
)。然后使用 popen
的等价物来执行进程。 envoy
本质上是 shell 对 |
标记所做的(将内容拆分到 |
然后使用 popen)。
envoy 没有做的是像 shell 那样解释 *
,就像使用某种 glob
函数扩展它以匹配文件一样。 Bash 确实如此。这就是我的答案。
一个有趣的练习是你向 envoy 贡献代码 :-) 并让它进行 globbing。