hfo*_*rat 4 shell zsh ps shell-script
我想写一个小包装器,ps
这样无论选项是什么,或者如果我 grep 结果,我都可以得到输出的第一行,ps
告诉我列是什么。例如, 的输出ps_wrapper -aux | grep thing
将类似于:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
name 33925 1.0 0.0 9972 5528 pts/0 Ss 19:34 0:00 /bin/thing
Run Code Online (Sandbox Code Playgroud)
我试着看看是否tee
有用,并尝试了类似的东西
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
name 33925 1.0 0.0 9972 5528 pts/0 Ss 19:34 0:00 /bin/thing
Run Code Online (Sandbox Code Playgroud)
但我很快意识到,当然,即使我“手动”写入/dev/stdout
,它仍然会通过管道传输到grep
。
我想打印我正在运行的实际命令的第一行,因为打印的列ps
可能会根据使用的选项而变化。
我正在使用 zsh,但如果有更合适的工具,我不介意使用其他工具。
感谢您的阅读。
一般来说,\xe2\x80\x9c 不可能绕过管道\xe2\x80\x9d,例如,将输出发送到没有管道时输出将去往的任何地方。但是,可以绕过管道,将输出重定向到您选择的另一个位置,例如终端。特殊文件/dev/tty
始终代表当前终端。
function ps_wrapper {\n tmpfile=$(mktemp)\n ps "$@" > $tmpfile\n head -n 1 $tmpfile >/dev/tty\n cat $tmpfile\n rm $tmpfile\n}\n
Run Code Online (Sandbox Code Playgroud)\n如果您 \xe2\x80\x9csave\xe2\x80\x9d 原始位置并通过文件描述符将其传递下来,也可以绕过管道。但你不能从ps_wrapper
函数中做到这一点。
function ps_wrapper {\n tmpfile=$(mktemp)\n ps "$@" > $tmpfile\n head -n 1 $tmpfile >&3\n cat $tmpfile\n rm $tmpfile\n}\n{ ps_wrapper \xe2\x80\xa6 | grep \xe2\x80\xa6; } 3>&1\n
Run Code Online (Sandbox Code Playgroud)\n有很多方法可以避免创建临时文件。我会提到一些。除非另有说明,如果您在变量和命令替换周围添加双引号,则此答案中的解决方案可以在 bash 中工作。
\n如果您愿意更改调用该函数的方式,可以在管道的右侧连续调用head
和。将读取并打印第一行,并将其余部分留给后继者使用。grep
head
ps \xe2\x80\xa6 | { head -n 1; grep \xe2\x80\xa6; }\n
Run Code Online (Sandbox Code Playgroud)\n您可以使用zsh或zsh 的内置类似功能 ( )进行过程替换来复制输出,将一个流发送到您选择的命令,将另一个流发送到您选择的命令。但是,如果您只是将每个流传输到一个命令,则两者之间将会发生竞争,如果速度不够快,第一行可能不会出现在顶部。它可能经常工作,因为速度相当快,但不能保证,例如,如果在磁盘缓存中但不在磁盘缓存中。tee
tee
multios
head -n 1
head
head
grep
head
ps | tee >(head -n 1 >/dev/tty) | grep \xe2\x80\xa6\nps >(head -n 1 >/dev/tty) | grep \xe2\x80\xa6 # zsh only, only if multios is not disabled\n
Run Code Online (Sandbox Code Playgroud)\n您可以使用 awk 显示第一行,然后传递其余行。
\nfunction ps_wrapper {\n ps "$@" | awk \'NR == 1 {print >"/dev/tty"} NR != 1 {print}\'\n}\n
Run Code Online (Sandbox Code Playgroud)\n说明:
\nNR
是行号。print
不带参数打印输入行。另一种方法是将过滤器功能构建到单个命令中。选择一个不会出现在参数中的字符串用作ps
分隔符,例如|
。
function pipe_preserving_first_line {\n local lhs\n lhs=()\n while [[ $1 != \'|\' ]]; do\n lhs+=($1)\n shift\n done\n shift\n "${lhs[@]}" | {\n head -n 1;\n "$@"\n }\n}\npipe_preserving_first_line ps u \\| grep foo\n
Run Code Online (Sandbox Code Playgroud)\n除了使用 grep 之外,您还可以使用ps
\ 的匹配功能,例如-C
通过命令名称来匹配进程。
ps uww -C mycommand\n
Run Code Online (Sandbox Code Playgroud)\n您可以使用pgrep
\ 的匹配工具来代替 grep。
ps -p $(pgrep -d, mycommand)\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
1016 次 |
最近记录: |