从shell管道中读取line,传递给exec,并保留到variable

bwitn5fc  于 2023-04-07  发布在  Shell
关注(0)|答案(2)|浏览(94)

我正在尝试通过Python脚本传递管道中的数据,并将此数据写入一个单独的变量,以便进一步处理

  • 脚本的主要目的是成为管道之间的一层,记录解析错误以及导致错误的原因。*

适用范围:

echo '{"user": "Basic dGVzdDp0ZXN0"}' | script.py | rotatelogs {....}

我写了一个脚本:

cmd = ["/usr/bin/jq -c \'.user |= if test(\"^[Bb]asic \") then .[6:] | @base64d | gsub (\":.*$\"; \"\")  else . end \'"]

with open('/dev/stdin') as f: 
        try:
            subprocess.run(cmd, check = True, shell=True)
        except subprocess.CalledProcessError:
            with open('/path/to/parseerror.log', 'w') as pfile:
                pfile.write(f.read())

www.example.com中的命令subprocess.run成功执行并产生其输出,但f.read()变为空如果我将变量f.read()的阅读移动到执行subprocess.run,那么我将获得变量的值,但命令subprocess.run将不会执行(获得空管道输入)。

with open('/dev/stdin') as f: 
        line=(f.read())
        try:
            subprocess.run(cmd, check = True, shell=True)
        except subprocess.CalledProcessError:
                ....

我怎样才能将命令的执行与来自管道的参数结合起来,并记录传入管道本身呢?主要目标是通过脚本传递命令执行,并将接收到的管道参数写入单独的文件

6qftjkof

6qftjkof1#

您的方法一直读到EOF,这就是read()所做的,没有留下任何输入供子进程读取。请尝试readline()
打开第二个stdin似乎也很奇怪。

import sys
...
print(sys.stdin.readline(), end='')
subprocess.run(cmd, stdin=sys.stdin, shell=True, check=True)

如果您只想运行一个命令,那么您可能可以使用get rid of shell=True

import shlex
...
subprocess.run(shlex.split(cmd), stdin=sys.stdin, check=True)

严格来说,stdin=sys.stdin并不重要(子进程将继承其父进程的标准输入,并根据需要消耗多少),但它记录了您的意图。
奇怪的是,即使使用一个readline(),我也会出现与您描述的相同的症状。我可以使用显式的read()来解决它:

subprocess.run(shlex.split(cmd), input=sys.stdin.read(), text=True, check=True)

...但如果您需要处理潜在的大量输入,这显然没有吸引力。
相反的情况不起作用;在一般情况下,该命令可以读取所有可用的输入,直到EOF(尽管有些命令,如head,不会),然后在子进程完成后,没有任何东西留给您的Python脚本读取。

h6my8fg2

h6my8fg22#

为了从echo "some data with spaces" | script.py这样的管道中读取数据,你可以用任何标准的输入法从stdin中读取数据。
类似地,要将数据传递到另一个进程,只需使用任何标准输出方法写入stdout。操作系统将为您处理重定向。
例如:

# script.py
for line in input():
    print(line)

现在就做

echo "my first line\nmy second line" | python script.py

你会得到这样的输出:

my first line
my second line

相关问题