我有一个程序可以生成有用的信息,stdout但也可以从stdin. 我想将其标准输出重定向到一个文件,而不在标准输入上提供任何内容。到目前为止,很好:我可以做到:
program > output
Run Code Online (Sandbox Code Playgroud)
并且不要在 tty 中做任何事情。
但是,问题是我想在后台执行此操作。如果我做:
program > output &
Run Code Online (Sandbox Code Playgroud)
程序将被挂起(“挂起(tty 输入)”)。
如果我做:
program < /dev/null > output &
Run Code Online (Sandbox Code Playgroud)
程序立即终止,因为它到达 EOF。
似乎我需要的是将program某些内容导入到无限期不执行任何操作且不读取的内容中stdin。以下方法有效:
while true; do sleep 100; done | program > output &
mkfifo fifo && cat fifo | program > output &
tail -f /dev/null | program > output &
Run Code Online (Sandbox Code Playgroud)
然而,这一切都非常难看。有有是一种优雅的方式,使用标准的Unix工具,以“什么都不做,无限期”(意译man true)。我怎么能做到这一点?(我这里优雅的主要标准:没有临时文件;没有忙碌等待或定期唤醒;没有异国情调的实用程序;尽可能短。)
让我详细描述一下这个问题:
我运行一些无人值守的脚本,这些脚本可以生成标准输出和标准错误行,我想按照终端模拟器显示的精确顺序捕获它们,然后向它们添加前缀,如“STDERR:”和“STDOUT:”。
我曾尝试对它们使用管道甚至基于 epoll 的方法,但无济于事。我认为解决方案是在 pty 使用中,尽管我不是这方面的高手。我还查看了Gnome 的 VTE的源代码,但这并没有多大成效。
理想情况下,我会使用Go而不是 Bash 来完成此操作,但我无法做到。由于缓冲,管道似乎自动禁止保持正确的行顺序。
有人能做类似的事情吗?或者这是不可能的?我认为,如果终端模拟器可以做到,那么它就不是——也许通过创建一个以不同方式处理 PTY 的小型 C 程序?
理想情况下,我会使用异步输入来读取这 2 个流(STDOUT 和 STDERR),然后根据我的需要重新打印它们,但输入顺序至关重要!
注意:我知道stderred但它不适用于 Bash 脚本,并且无法轻松编辑以添加前缀(因为它基本上包含了大量系统调用)。
更新:在两个要点下面添加
(可以在我提供的示例脚本中添加亚秒随机延迟,以证明结果一致)
更新:正如@Gilles 指出的那样,这个问题的解决方案也将解决另一个问题。但是,我得出的结论是,不可能在这里和那里做所要求的事情。当使用2>&1两个流在 pty/pipe 级别正确合并时,但要单独使用流并以正确的顺序使用,确实应该使用涉及系统调用挂钩的stderred方法,并且可以在许多方面被视为脏。
如果有人可以反驳上述内容,我将渴望更新这个问题。
如果我调用某个命令,例如,echo我可以在其他几个命令中使用该命令的结果tee。例子:
echo "Hello world!" | tee >(command1) >(command2) >(command3)
Run Code Online (Sandbox Code Playgroud)
使用 cat 我可以收集几个命令的结果。例子:
cat <(command1) <(command2) <(command3)
Run Code Online (Sandbox Code Playgroud)
我希望能够同时做这两件事,这样我就可以tee在其他东西的输出上调用这些命令(例如echo我写的),然后在一个输出上收集所有结果cat.
保持结果为了这一点很重要,这意味着输出的线路command1,command2并且command3不应该纠缠在一起,但订购的命令是(因为它与发生cat)。
可能有比cat和更好的选择,tee但这些是我目前所知道的。
我想避免使用临时文件,因为输入和输出的大小可能很大。
我怎么能这样做?
PD:另一个问题是这种情况发生在循环中,这使得处理临时文件变得更加困难。这是我拥有的当前代码,它适用于小型测试用例,但是在以某种我不理解的方式从 auxfile 读取和写入时,它会创建无限循环。
somefunction()
{
if [ $1 -eq 1 ]
then
echo "Hello world!"
else
somefunction $(( $1 - 1 )) > auxfile
cat <(command1 < auxfile) \
<(command2 < auxfile) \
<(command3 < auxfile)
fi …Run Code Online (Sandbox Code Playgroud) $RANDOM每次访问特殊变量时都会有一个新值。在这方面,它让人想起某些语言中的“生成器”对象。
有没有办法在中实现这样的东西zsh?
我试图用命名管道来做到这一点,但我没有找到一种以受控方式从 fifo 中提取项目而不终止“生成器”进程的方法。例如:
% mkfifo /tmp/ints
% (index=0
while ( true )
do
echo $index
index=$(( index + 1 ))
done) > /tmp/ints &
[1] 16309
% head -1 /tmp/ints
0
[1] + broken pipe ( index=0 ; while ( true; ); do; echo $index; index=$(( ...
Run Code Online (Sandbox Code Playgroud)
有没有其他方法可以在 zsh 中实现这种生成器类型的对象?
编辑:这不起作用:
#!/usr/bin/env zsh
FIFO=/tmp/fifo-$$
mkfifo $FIFO
INDEX=0
while true; do echo $(( ++INDEX )) > $FIFO; done &
cat $FIFO
Run Code Online (Sandbox Code Playgroud)
如果我将上述内容放在脚本中并运行它,则输出很少是预期的单行
1
Run Code Online (Sandbox Code Playgroud)
相反,它通常由几个整数组成;例如
1
2 …Run Code Online (Sandbox Code Playgroud) 我rbenv在机器上安装了(ruby 版本管理器),它的工作原理是这样的:
$ rbenv local
2.3.1
Run Code Online (Sandbox Code Playgroud)
写入标准输出我的 ruby 的本地版本。我想拯救这个版本并在一个变量中声明它以在另一个场合重用。
$ declare -r RUBY_DEFINED_VERSION=$(rbenv local)
$ echo Using ruby version $RUBY_DEFINED_VERSION
Using ruby version 2.3.1
Run Code Online (Sandbox Code Playgroud)
有用!
但我不想使用子外壳来完成工作(使用$()或``)。我想使用相同的外壳,我不想创建一个tmp文件来完成这项工作。
有没有办法做到这一点?
注意: declare -r不是强制性的,它可以是一个简单的var=FOOBAR.
我读过的内容$coproc < command >不同于$< command > &与在子 shell 进程中coproc执行的command
但当我测试它时,它的工作原理就像$< command > &. 测试如下:
第一:测试行为$< command > &。
$nano &在tty1上$ps -t tty1 --forest表明 nano 进程是 -bash 进程的子进程(登录 bash shell 进程 -> 未创建子 shell 进程)第二:测试行为$coproc < command >
$coproc nano在tty1上$ps -t tty1 --forest上面相同(没有创建子 shell 进程)也是如此$coproc < command >和一样吗$< …
执行以下脚本
#!/usr/bin/bash
while true
do
ab -c 700 -n 100000000000 -r http://crimea-post.ru/ >>crimea-post & ab -c 700 -n 100000000000 -r http://nalog.gov.ru/ >>nalog
done
Run Code Online (Sandbox Code Playgroud)
做的完全一样
#!/usr/bin/bash
while true
do
ab -c 700 -n 100000000000 -r http://crimea-post.ru/ >>crimea-post
ab -c 700 -n 100000000000 -r http://nalog.gov.ru/ >>nalog
done
Run Code Online (Sandbox Code Playgroud)
根据我的经验,第一个脚本创建nalog文件的速度比第二个脚本(10 多分钟后)更快(几秒钟内),这表明后者需要等待ab -c 700 -n 100000000000 -r http://nalog.gov.ru/ >>nalog完成。情况不应该是这样,因为从我到目前为止的研究来看,第二个脚本应该ab -c 700 -n 100000000000 -r http://nalog.gov.ru/ >>nalog在不等待ab -c 700 -n 100000000000 -r http://crimea-post.ru/ >>crimea-post完成的情况下开始。我希望这两个ab命令同时执行,我如何在 …
bash ×4
pipe ×2
shell ×2
cat ×1
concurrency ×1
coprocesses ×1
fifo ×1
ipc ×1
parallelism ×1
shell-script ×1
stdin ×1
stdout ×1
subshell ×1
tee ×1
variable ×1
zsh ×1