誤って入力を過度のページ付けにパイプした後、対話型コマンドを再開しますか?

誤って入力を過度のページ付けにパイプした後、対話型コマンドを再開しますか?

次のスクリプトを考えてみましょう。

$ 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を受け取ります。CtrlCbashsleepless

sleep受ければ死ぬのだから死ぬのだbashlessSIGINTを傍受し、次のように処理します。現在のジョブをキャンセル

しかしbash、死なないと、読み続けることができますless

したがって、あなたができることは、bashSIGINTが死を招くのを防ぐことです。

(trap '' INT; bash example.sh) | less

Ctrlその後、+を使用してスクリプトによって開始されたプロセスに影響を与えることなくC中断できます。lessbash

スクリプトを停止するには、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

関連情報