我使用 shell 作业控制将较长时间运行的任务踢到后台,这样我就可以在它们搅动数据时继续运行。
我可以看到我正在运行的作业jobs
,例如,
jobs
[2]- Running su - root -c "..." & (wd: /backup/rsnapshot)
[3]+ Running sleep 60 &
我可以使用以下命令控制其中任何一个%
工作规范语法,例如fg %su
or kill %3
。
如果我使用的话,jobs -l
我也会得到 PID:
jobs -l
[2]- 31736 Running su - root -c "..." & (wd: /backup/rsnapshot)
[3]+ 2269 Running sleep 60 &
使用bash
我有jobs -x
,但是这个不是 POSIX。这是翻译这些的唯一方法吗%
工作规范值到 PID 中,或者是否有明智的(更好)替代方法?那么其他的贝壳呢?
jobs -x echo %3
2269
我的目标用例是%
工作规范待扩大透明地在命令行上输入相应的 PID,这样在这样的命令中 就会%2
被命令视为31736
pidtree %2 # pidtree 31736
这可以被处理,jobs -x pidtree %2
但不是那么优雅或方便。
我想要至少一个答案 Targeting bash
,但欢迎为具有作业控制的其他 shell 做出贡献,特别是如果您有 POSIX 解决方案。
答案1
您可以通过从当前作业列表中动态bash
提供自定义设置变量来接近这一点。$PROMPT_COMMAND
概念验证:
$ PROMPT_COMMAND='unset ${!j*}; eval "$(jobs -l | awk '\''{gsub("[^[:digit:] ]", ""); printf "j%d=%d\n", $1, $2}'\'')"'
然后,您将pidtree $j2
代替pidtree %2
,假设 中 没有数字,$IFS
否则您必须引用 ,$j2
因此需要多敲两次键。
答案2
如果您只想对几个命令执行此操作,那么可编程完成将是一个选项。这很可能不是 POSIX,但至少可以在多个 shell 中使用(并且底层机制甚至不必相同)。
所以你可以输入pidtree %2
Tab,shell 会将其转换为
pidtree 31736
我认为这是优雅和方便的。
缺点:保留这些命令的现有完成配置需要手动干预(例如:首先运行您的函数;如果不匹配,则使其调用原始函数)。
_pidtree () {
local job pid
if [[ ${COMP_WORDS[COMP_CWORD]} =~ ^%[1-9][0-9]* ]]; then
job="${COMP_WORDS[COMP_CWORD]:1}"
pid="$(jobs -l | awk -v job="$job" '$1 ~ "^\\[" job "\\]" { print $2; }')"
COMPREPLY=("$pid")
fi
}
complete -F _pidtree pidtree
这适用于bash
.它可以在没有 的情况下完成awk
,并且当然可以以更兼容的方式完成。
包含换行符的作业可能会出现问题,但由于这是您的交互式 shell,因此似乎不存在被利用的风险。
答案3
创建后台作业时只记住 PID 不是最简单的吗?
bash
:
declare -a bgjobpids
[...]
do_some_thing &
pid=$!
index=${#bgjobpids[@]}
bgjobpids[index]=$pid
[...]
do_some_thing_else &
pid=$!
index=${#bgjobpids[@]}
bgjobpids[index]=$pid