仅当进程在后台运行时才隐藏进程的stdout
只有当它在后台运行时,我怎么能隐藏进程的标准输出?
例如,
test.sh
#!/bin/bash for i in $(seq 200); do echo $i done
现在,我运行脚本。 我停下来 我把它放回去测试它继续运行。 然后我把它放在背景上,但它继续在标准输出中打印,我无法继续工作。 有没有办法只在背景时重定向或隐藏过程输出?
dione@saturno:~$ ./test.sh 1 2 3 ^Z [1]+ Detenido ./test.sh dione@saturno:~$ fg %1 ./test.sh 4 5 6 ^Z [1]+ Detenido ./test.sh dione@saturno:~$ %1 & [1]+ ./test.sh & dione@saturno:~$ 7 8 9 10 11 12 13 14 15 fg ./test.sh 16 17 ^C dione@saturno:~$
重定向正在运行的进程的输出并不容易 。 但如果你从一开始就工作,可能会有其他选择:
some_long_runnning_command | tail -n 1000 & pkill -STOP tail
使用这种方法,由于tail
有SIGSTOP
发送给它,它将不会输出任何东西,直到你使用fg
(或类似的东西)明确地将它带到前台,直到脚本完成。 调整1000
以获得任意数量的行。
一个更好的选择可能是grep
:
some_long_runnning_command | grep . --color=never & pkill -STOP sed
您可以发信号通知SIGCONT
和SIGSTOP
grep
以根据需要启动和停止输出。
这可能与上面链接的SO问题中的打开文件描述符的重新附加相结合(可能与本答案中的脚本一起),以便可以使用已经打开的进程完成此操作。
如果缓存确实是grep
一个问题,正如Volker Siegel指出的那样 ,那么人们可能会考虑使用更复杂的命令集。 首先,请注意sort
使用临时文件 ,因此缓冲应该不是问题。 它将像tail
和grep
的组合一样 – 等待命令完成,如tail
,并保持整个输出,如grep
。 就像是:
some_long_runnning_command | awk '{$0=";"$0}1' | sort -k1.1,1.1 --stable | sed 's/^;//' & pkill -STOP sed
这里的损失是你不能随意启动和停止输出,并且在无用的sort
花费了大量的计算,以及添加和删除的工作;
。
进一步的测试显示Volker确实是正确的:
对于像(称为test.sh
)这样的脚本:
#! /bin/bash for i in $(seq 1000000); do echo $i; echo $i > /tmp/log; done
和命令:
./test.sh | grep . --color=never & pkill -STOP grep
/tmp/log
被固定在12768(具有相似的数字。并且使用命令
./test.sh | awk '{$0=";"$0}1' | sort -k1.1,1.1 --stable | sed 's/^;//' & pkill -STOP sed
脚本运行完成( /tmp/log
有1000000
)没有窥视sed
。
我仍然没有设法将它与GDB方法集成,但是因为它可以作为一个函数使用,类似于John1024 。 问题是你无法知道进程是否已经结束,因为shell只会在整个作业结束时通知你。 所以你必须使用检查function:
function check () { local PROC=${1:-$(jobs -p %%)} kill -0 $PROC 2>/dev/null && echo "The process is still running." || echo "The process is not running." } function bg () { "$@" | awk '{$0=";"$0}1' | sort -k1.1,1.1 --stable | sed 's/^;//' & local PID=$! sleep 0.1s kill -STOP $PID cat <
您可以将"$@"
包装在另一个函数中,该函数将在作业完成后通知您,使用notify-send
或write
类的东西。
这是一个很好的练习,但最终最简单的方法是重定向到/dev/null
并忘记输出: 如何将后台应用程序的输出重定向到/ dev / null 。
仅当脚本在后台运行时,此脚本才会将stdout重定向到/dev/null
:
#!/bin/sh case "$(ps -o stat= -p $$)" in *+*) : ;; *) exec 1>/dev/null ;; esac for i in $(seq 200); do echo $i done
这里的关键是当作业是前景时, ps
stat
字段中有一个+
。 如果缺少+
,我们在后台。
如果你想为某些东西而不是其他东西保持stdout,我们可以为自由选择的输出创建一个文件描述符3,并保持stdout对其他输出有效。 下面的脚本实现了这一点。 它将循环输出发送到文件描述符3.如果作业在前台运行,则文件描述3为stdout;如果作业在后台运行,则为/dev/null
:
#!/bin/sh case "$(ps -o stat= -p $$)" in *+*) exec 3<&1 ;; *) exec 3>/dev/null ;; esac for i in $(seq 200); do echo $i done >&3
在背景和静默中运行任何命令的简单方法
创建这个bash函数:
bkg() { "$@" >/dev/null & }
然后,无论何时你想要一个嘈杂的命令,比如seq 200
,在后台输入:
bkg seq 200
该命令将在后台运行,其stdout将被处理掉。
要使bkg
永久定义,请将定义放在~/.bashrc
。