私は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
オプションを使用して、実行するコマンドを含むファイルを指定することもできます。リダイレクトがない場合、-f
atは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 checkwinsize
Bash 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を使って良い結果を得ました。