アップデート_1

アップデート_1

私はUbuntu Server 16.04を使用しています。atこのユーティリティを使用して、echo特定の日時を指定せずに現在のセッションで今から1分(現在の時刻より1分前)にいくつかのタスクを実行したいと思います。

失敗します。

echo 'hi' | at 1m

at私がこれを選択した理由sleepは、睡眠が現在のセッションを妨げるため、ほとんどの時間を使用するセッションよりも他のセッションでコマンドを遅延させるのに適しているためです。 AFAIRはatそうしませんし、私の会議を妨げません。

アップデート_1

Pied Piperの答えに基づいて、以下を試しました。

(sleep 1m; echo 'hi')  &

このアプローチには問題があります。 「hi」ストリームがプライマリプロンプト内に印刷され、_それを含むプライマリプロンプトの下に空のセカンダリプロンプト()も追加されます。以下を参照してください。

USER@:~# (sleep 1m; echo 'hi')  &
[1] 22731
USER@:~# hi
^C
[1]+  Done

更新_2

Peter Coddの答えに基づいて、以下を試しました。

(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)

これはBash 4.4ではうまく機能しますが、以前のバージョンではうまくいかないようです(答えのコメントを参照)。私は個人的に私の環境でBash 4.3を使用します。

答え1

正しい使い方は時間仕様があるat <timespec>ところです。<timespec>この-fオプションを使用して、実行するコマンドを含むファイルを指定することもできます。リダイレクトがない場合、-fatはstdin(標準入力)から実行するコマンドを読み取ります。

あなたの例では、Enterキーを押してから1分後に「some command」を実行したい場合(以下の例では「echo hi」として「some command」を選択しました)、使用するターゲット<timespec>はですnow + 1 minute。したがって、目的の結果を得るには、1行の解決策として次を使用します。

echo 'echo hi' | at now + 1 minute

その後echo hi、1分後にコマンドが実行されます。ここでの問題は、echo hiコマンドが仮想ttyのatコマンドによって実行され、出力がユーザーのメールボックスに送信されることです(正しく設定されている場合 - UNIXシステムのより広範な説明が必要であり、この質問の範囲外です)。 )。最も重要なのは、echo hiコマンドを実行したのと同じ端末で直接結果を表示できないことです。最も簡単な方法は、次のような「一部のファイル」にリダイレクトすることです。

echo 'echo hi > /tmp/at.out' | at now + 1 minute

上記の例では、「some file」があり、予想される結果は、/ tmpの下に1分後に「hi」というテキストを含む/tmp/at.outファイルが生成されることです。at.out

now + 1 minute上記の例に加えて、他の多くの時間仕様、さらにはいくつかの複雑な仕様も使用できます。 atコマンドは、次の例のように、人間が読めるコマンドを解釈するのに十分スマートです。

now + 1 day, 13:25, mid‐night, noon, ...

可能なバリエーションは非常に広く、日付、相対時間、絶対時間などが含まれる可能性があるため、可能な時間指定の詳細については、atのマニュアルページを参照してください。

答え2

sleepサブシェルで実行:

(sleep 60; echo -e '\nhi')  &

注:Linuxでは、省電力パラメータを秒単位で指定することも、サフィックスs / m / h / d(秒、分、時間、日)を使用することもできます。 BSDでは、引数は秒単位でなければなりません。

答え3

「hi」ストリームは、プロンプトstdinではなくプロンプト(in)に印刷されます。stdout

いいえいいえ「あなたに封印されましたstdin。」

Enterキーを押すと、コマンドはhi実行されません。カーソルがプロンプトの後ろにあるときにecho背景が印刷されるだけです。hi


おそらくあなたは欲しいでしょう先行改行文字の印刷、良い(sleep 1m && echo -e '\nhi' &)。 (echoシェルの要件に合わせて調整するか、printf移植性のために調整してください。)

&バックグラウンドタスクを「拒否」するためにサブシェルに入れたので、これを避けることもできます[1]+ Done&&コマンド間では、複合コマンドチェーン全体に対して機能するため、シャットダウンを待たずに&すぐにシェルプロンプトに戻ります。sleep(sleep 1; echo ... &)

結果は次のとおりです(1秒遅れ)。

peter@volta:~$ (sleep 1 && echo -e '\nhi' &)
peter@volta:~$ 
hi
       # cursor is at the start of this empty line.

Bashは何が印刷されたのか分からないechoので、プロンプトを再印刷するか、画面を消去する必要があることを知りません。これは手動で行うことができますcontrol-L

シェル関数を書くことができますecho完了したら、bashにプロンプ​​トを再印刷します。。これにより、echo "$PS1"すでに入力された文字は再現されません。 kill -WINCH $$私のシステムでは、bashは画面を消去せずにプロンプ​​ト行を再印刷し、hiプロンプトの前に別の行を残します。 SIGWINCHはWINdowのサイズが変更されると自動的に送信され、これに対するbashの応答は正確に私たちが望むように行われます。

他のシェルでも機能できますが、100%移植可能/POSIXにすることはできません。 (残念ながら、これはbash4.3ではなくbash4.4でのみ動作するか、私が知らないいくつかの設定によって異なります。)

  # bash4.4
peter@volta:~$ (sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
peter@volta:~$ ljlksjksajflasdf dfas      # typed in 2 seconds
hi
peter@volta:~$ ljlksjksajflasdf dfas      # reprinted by Bash because of `kill -WINCH`

睡眠パラメータとメッセージを使用して、シェル関数で簡単にラップできます。

bash 4.3はSIGWINCH後にプロンプ​​トを再印刷しないため、ここでは機能しません。両方のシステムで有効にしましたが、shopt -s checkwinsizeBash 4.4システム(Arch Linux)でのみ機能します。

機能しない場合は、(sleep 2 && echo -e '\nhi' && echo "$PS1" &)コマンドラインが空の場合は「動作」できます。 (PROMPT_COMMAND設定可能性も無視します。)


後でタイマーが実行されたときにターミナルで実行できるタスクとターミナル出力を混在させる本当にきちんとした方法はありません。何かをスクロールしている場合は、less簡単に見逃すことができます。

インタラクティブな結果があるものを探している場合は、オーディオファイルを再生することをお勧めします。たとえば、コマンドラインプレーヤーを使用すると、mpv(MPlayer2の良いフォーク)。または、ビデオファイルを選択して新しいウィンドウを開きます。

(sleep 1 && mpv /f/share/music/.../foo.ogg </dev/null &>/dev/null &)

echo新しいxterm/konsole/gnome-terminalを開きたい場合があります。コマンドで終了した後に端末を開いたままにするオプション。

答え4

@ Peter Cordesの回答をこの回答と組み合わせる https://stackoverflow.com/questions/23125527/how-to-return-to-bash-prompt-after-printing-output-from-Backgrounded-function/23125687#23125687

以下のコードは、私が変更した後者の答えから来ています。 a.outファイルにコンパイルします(必要な名前で指定)。

#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        char *tty = "/dev/tty";
        if (argc > 1)
                tty = argv[1];
        int fd = open(tty, O_WRONLY);

        int i;
        char buf[] = "\n";
        for (i = 0; i < sizeof buf - 1; i++)
                if (ioctl(fd, TIOCSTI, &buf[i]))
                        perror("ioctl");
        close(fd);
        return 0;
}

次に、次のコマンドを実行します。 (私はa.outを/tmp/ディレクトリに入れました。これをあなたのものに変更する必要があるかもしれません)

(sleep 2 && echo -e '\nhi' && /tmp/a.out &)

または

(sleep 2 && echo -e '\nhi' && /tmp/a.out /proc/$$/fd/0 &)

ちなみに、kill -WINCH $$私はGentooでBash 4.3を使って良い結果を得ました。

関連情報