特定の文字列を出力するときにコマンドを一時停止するには?

特定の文字列を出力するときにコマンドを一時停止するには?

他のコマンドの出力と指定された文字列が印刷されたときを監視するツールが必要です。監視対象のコマンドを停止するには「エラー」が発生します。その後、一部の環境とファイルを変更して作業を続けます。可能ですか?

編集:はい:

次のjob.shがあります。

for i in $(ls)
do
    echo file $i
    sleep 0.1
    cat $i
done

a.txtファイルとb.txtファイルを含むフォルダで実行するときに編集用にfile b.txtjob.shを印刷して一時停止し、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;
}

たとえば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、、呼び出しprintfsleep開始アドレスです。

% 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もう1つのアイデアは、最も賢明なオプション(ソースからプログラムを再コンパイルすること)が不可能であると仮定し、プログラムの動作方法を調整するために使用することです。別のオプションは期待どおりに実行する C バイナリパッチ

答え2

read続行する前に、これを使用してユーザー入力を待つことができます。

例:

プログラムはループを実行し、出力を印刷してls -lhtrユーザー入力(Enterまたは他の文字を押す)を待ってから、出力を再印刷して無限ループでプロセスを続行します。

#!/bin/bash

while (true); do
        ls -lhtr;
        read i;
done

したがって、デフォルトでls -lhtr監視する必要がある出力を持つコマンドを使用できます。環境とファイルを変更したら、任意のキーをもう一度押してコマンド出力を監視し続けることができます。

関連情報