![如何在命令输出某些字符串时暂停命令?](https://linux22.com/image/136867/%E5%A6%82%E4%BD%95%E5%9C%A8%E5%91%BD%E4%BB%A4%E8%BE%93%E5%87%BA%E6%9F%90%E4%BA%9B%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%97%B6%E6%9A%82%E5%81%9C%E5%91%BD%E4%BB%A4%EF%BC%9F.png)
我需要一个工具来监视其他命令的输出,以及何时打印指定的字符串,例如。 “错误”,停止受监控的命令。然后我修改一些环境和文件并继续工作。是否可以?
编辑:示例:
有以下 job.sh
for i in $(ls)
do
echo file $i
sleep 0.1
cat $i
done
当在包含文件 a.txt 和 b.txt 的文件夹中运行时,我想在打印 job.sh 后暂停file b.txt
它进行编辑,然后继续 job.sh 并查看新的 b.txt 内容。我不能碰 job.sh,因为它实际上是编译的 C 程序。睡眠象征着暂停不必立即,但仍然要快。
答案1
% ./mystery
a
b
c
%
我们可以STOP
向程序发出信号,然后CONT
继续执行;以下 TCL 代码等待b
出现在输出中,然后停止该进程,该进程应保持停止状态,直到用户键入要expect_user
执行的行(至少是换行符)。
#!/usr/bin/env expect
spawn -noecho ./mystery
set spid [exp_pid]
expect -ex b { exec kill -STOP $spid; send_user "STOP\n" }
expect_user -re . { exec kill -CONT $spid }
expect eof
这当然有各种各样的问题,例如mystery
运行速度太快,或者输出是否被缓冲等等。我必须放慢 C 速度并关闭缓冲才能解决问题:
% cat mystery.c
#include <stdio.h>
#include <unistd.h>
int main(void)
{
setvbuf(stdout, (char *) NULL, _IONBF, (size_t) 0);
printf("a\n");
sleep(1);
printf("b\n");
sleep(1);
printf("c\n");
return 0;
}
通过在调试器下运行 AC 程序可以更好地控制它,例如gdb
;与对 I/O 做出反应相比,断点是在代码中的某个特定点停止执行更为准确的方法。调试符号会有所帮助,但不是必需的:
% gdb mystery
Reading symbols from mystery...(no debugging symbols found)...done.
(gdb) quit
% otool -dtv mystery | grep callq
0000000100000f26 callq 0x100000f70
0000000100000f32 callq 0x100000f6a
0000000100000f3c callq 0x100000f76
0000000100000f48 callq 0x100000f6a
0000000100000f52 callq 0x100000f76
0000000100000f5e callq 0x100000f6a
所以这实际上是在 Mac 上(反汇编会因平台而异)。以上是setvbuf
、printf
、 和sleep
调用 so 以及起始地址
% otool -dtv mystery | sed 3q
mystery:
_main:
0000000100000f06 pushq %rbp
% perl -E 'say 0x0000000100000f52 - 0x0000000100000f06'
76
% gdb mystery
Reading symbols from mystery...(no debugging symbols found)...done.
(gdb) b *main + 76
Breakpoint 1 at 0x100000f52
(gdb) r
Starting program: /Users/jhqdoe/tmp/mystery
a
b
Breakpoint 1, 0x0000000100000f52 in main ()
(gdb)
然后您可以做任何必要的事情并根据需要继续该程序。
另一个想法是使用来LD_PRELOAD
调整程序的行为方式,当然假设最明智的选择(从源代码重新编译程序)是不可能的。另一种选择是修补 C 二进制文件以使其按预期运行。
答案2
您可以使用read
它等待用户输入后再继续
例子:
该程序运行一个循环并打印 的输出ls -lhtr
,等待用户输入(按 Enter 或任何其他字符),然后再次打印输出并以无限循环继续该过程。
#!/bin/bash
while (true); do
ls -lhtr;
read i;
done
所以基本上ls -lhtr
,你可以使用你需要监控其输出的命令,一旦修改完环境和文件,你可以按任意键再次继续监控命令输出