bash脚本如何检测它是否在后台运行?


Answers:


30

报价man ps

过程状态码

   Here are the different values that the s, stat and state output
   specifiers (header "STAT" or "S") will display to describe the state of
   a process.
   ...
   +    is in the foreground process group

因此,您可以执行一个简单的检查:

case $(ps -o stat= -p $$) in
  *+*) echo "Running in foreground" ;;
  *) echo "Running in background" ;;
esac

当然,在$(...)中调用的任何内容本身都是在后台运行的。我想过程组虽然很重要,但不能否认它有效。
Ed Randall

2

查看文件“ /etc/bash.bashrc”。

具有“ $ PS1”的行。然后执行“ man bash”并查找令牌PS1。

[ -z "$PS1" ] && return

退出非交互式脚本。


1

以前的所有解决方案都涉及生成程序等。非常非常丑陋,因为.bashrc每次启动bash shell时都会调用它,因此这些解决方案结束了1000个进程的启动。

更干净的是问bash本身:bash有一个预定义的变量$-,如果它在交互式shell中运行,则它带有“ i”。例如,将其放入您的.bashrc更加干净,便宜得多,而且最重要的是,它将始终有效!

case "$-" in 

    *i*) # interactive shell

    ;;
esac

你为什么在喊?看起来非常非常丑陋 ……
Pierre.Vriens

简单,正确的解决方案。
Ed Randall

0

虽然您可能认为检查shell是否以交互方式运行会产生相同的结果,但实际上并非如此。这个概念看起来很相似,但实际上是不同的。多亏了Expect,您可以在后台供稿输入中运行交互式脚本。同样,您可以使用带有-l参数的bash启动脚本。因此,我们不能依靠bash交互性来检查脚本是在后台还是在前台运行。

因此,devnull的答案是正确的。为了确定进程是否在前台运行,ps实用程序检查进程组(pgrp)是否与与会话的控制终端(tpgid)关联的进程组id相同,+根据该进程在输出中添加一个符号州。

知道这一点,我们绝对可以拥有测试的纯bash版本:

#!/usr/bin/env bash

IFS=$' '
retval=($(</proc/$$/stat))
IFS=$' \t\n'
if [[ "${retval[3]}" == "${retval[7]}" ]]; then
    echo "Background" > ./result.txt
else
    echo "Foreground" > ./result.txt
fi
exit

在上面的代码中,我们将结果输出到文本文件中,因为stdout在后台运行进程时未连接。

请注意,表的第4和第8元素分别对应于pgrptpgid请参见手册页的/ proc / [pid] / stat部分 - man 5 proc)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.