如何在命令输出某些字符串时暂停命令?

如何在命令输出某些字符串时暂停命令?

我需要一个工具来监视其他命令的输出,以及何时打印指定的字符串,例如。 “错误”,停止受监控的命令。然后我修改一些环境和文件并继续工作。是否可以?

编辑:示例:

有以下 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 上(反汇编会因平台而异)。以上是setvbufprintf、 和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,你可以使用你需要监控其输出的命令,一旦修改完环境和文件,你可以按任意键再次继续监控命令输出

相关内容