次のスクリプトを考えてみましょう。
$ cat example.sh
#! /usr/bin/env bash
for i in {1..90}
do
printf '%s\n' "$i"
done
sleep 10
printf '91\n'
sleep 10
printf 'done\n'
出力が次のようにパイプラインが少ないと仮定します。
$ bash example.sh | less
90行まで下にスクロールすると、もう一度上にスクロールして検索し、提供されているless
他の対話型コマンドを使用できます。ただし、egj
またはline 90を使用しようとすると、Ctrl-N
他の
less
入力行が利用可能になるまで対話型コマンドへの応答が停止します。スペースバーを使用して90行を超えてページ全体をスクロールしようとすると、ページ全体の入力が可能に
less
なるかEOFが受信されるまで、対話型コマンドへの応答が停止します。
以前の出力を見たい、利用可能な行を探索していて、より多くの行が表示されるのを待つ必要があることを認識していない場合(任意の時間がかかる場合があります)、これはお勧めできません。
Ctrl-C を使用して SIGINT を送信すると、すぐにやり直すことができますが、less
パイプからより多くの入力を受け取ることは停止します。
このスクリプトは再現しやすい例ですが、壊れたシンボリックリンクの検索など、出力行をゆっくり生成する長期実行コマンドに置き換えることができます。
$ find $HOME -xtype l | less
または私のホームディレクトリで誰でも読むことができます:
$ find $HOME -perm 777 | less
またはstdout
。
less
パイプで必要な入力行が生成されるのを待たずに、より多くの入力を待たずにインタラクティブコマンドに戻るようにする方法はありますか?
答え1
存在する
bash example.sh | less
パイプ全体が前景に配置されます(前景プロセスグループには、実行中のプロセスbash
と生成されたすべてのプロセスの両方が含まれています)。したがって、+をless
押すとすべてSIGINTを受け取ります。CtrlCbash
sleep
less
sleep
受ければ死ぬのだから死ぬのだbash
。less
SIGINTを傍受し、次のように処理します。現在のジョブをキャンセル。
しかしbash
、死なないと、読み続けることができますless
。
したがって、あなたができることは、bash
SIGINTが死を招くのを防ぐことです。
(trap '' INT; bash example.sh) | less
Ctrlその後、+を使用してスクリプトによって開始されたプロセスに影響を与えることなくC中断できます。less
bash
スクリプトを停止するには、SIGTERMを使用してCtrlSIGQUITを\送信CtrlできZますkill %
。
ここで 1 は SIGINT のため終了します。 SIGINTが正常に処理され終了するbash
と、sleep
状況は異なります。これはsleep
他のシェルで実行される特別なSIGINT処理です。bash
答え2
あなたの質問を正しく理解したら、あなたが望む動作は、睡眠を中断して対話型モードにvim
戻ることです:
。
その答えは、スリープ関数をどのように処理するかによって異なりますが、それsleep
自体は通常のシェルコマンドではなく、特定の時間に実行されるダミージョブを生成する非常に特別なコマンドなので、割り込み処理を考慮する必要があります。ただし、スクリプトを変更すると、動作を簡単に達成できます。
#!/bin/bash
trap 'kill $(jobs -p)' INT
for i in {1..90}
do
printf '%s\n' "$i"
done
sleep infinity &
wait
printf '91\n'
sleep 10 &
printf 'done\n'
テストのために無期限の待機状態になるように元のスクリプトをいくつか修正しました。
90番線に達して通り過ぎようとすると、システムがsleep
長くかかるでしょう。終了するにはをクリックしてくださいCTRL+C。信号トラップのおかげでsleep
操作が中断されるだけでなく、目的のコンテンツ:
とその機能も返されます(実行後にキーを押す必要があるかもしれませんCTRL+C)。また、90行目を超えて移動しようとすると、スクリプトの実行が最初のジョブを通過したため、91行目がすぐに印刷されますsleep
。
答え3
最も悪い解決策は、以下を使用することですsetsid(1)
。
setsid bash example.sh | less
または
setsid find $HOME -xtype l | less
または
setsid find $HOME -perm 777 | less
「最も悪い点」はsetsid(1)
コマンドとして非標準のLinux-ismなので、まだ利用できない場合は、最も近いパッケージマネージャからインストールする必要があるだけでなく、(実際に移植可能)問題のコマンドが次のようなためです。また、職業管理から抜け出すことができるので、本物ps x
停止して見つかったPIDを使用して手動でkillコマンドを使用する以外は選択肢はありません。
他のオプションもありますが、すべて携帯性や人間工学的問題があります。比較する:https://unix.stackexchange.com/a/736048/54340