ターミナルでx時間間隔ごとにコマンドを繰り返しますか?


142

ディレクトリをチェック または監視するためのコマンドを実行できるように、時間間隔ごとにコマンドを繰り返すにはどうすればよいですか?

スクリプトは必要ありません。ターミナルで実行する単純なコマンドが必要です。

回答:


219

watchコマンドを使用できます 。watchは、指定されたコマンドを定期的に実行するために使用されます。

ターミナルを開き、次を入力します。

watch -n x <your command>

xを希望する秒単位の時間に変更します。

watchコマンドとそのオプションの使用に関する詳細については、man watchこのリンクを実行するかアクセスしてください。

たとえば、次のコマンドは、同じターミナルで60秒ごとにデスクトップディレクトリの内容をリストするため、変更が発生したかどうかを確認できます。

watch -n 60 ls -l ~/Desktop

34
+1。ただし、拡張を使用する場合は注意してください。たとえば、違い試すwatch -n 1 'echo $COLUMNS'watch -n 1 echo $COLUMNS、あなたの端末のサイズを変更する-前者は毎秒展開されているが、後者は一度しか展開される前に watch開始されます。
l0b0 14年

それは魅力のように動作します!Ty nux

私はこのソリューションを持っている問題は、プロセスとして時計を実行し、ちょうどバックグラウンドで実行されている、それを残して(と例えば&否認)することができないということです
Cestarian

2
watch「history enabled」タイプのコマンドで使用する方法はありますか?を使用するのwatchが大好きですが、最後の実行だけでなく、以前の実行のログも表示したい場合があります。そして、はい、スクリプト(while true)を使用してこれを達成できることは知っていますが、watchユーティリティを使用する方がずっときれいです!
rinogo

これはより単純なコマンドでは機能しましたが、パイプライン化されたコマンドチェーンではこれは機能しませんでした。grep 'calling' | wc -l
スディップバンダリ

90

nuxの答えとは別に、ターミナルでこのコマンドを使用することもできます。

while true; do <your_command>; sleep <interval_in_seconds>; done

while true; do ls; sleep 2; done

このコマンドはls、2秒間隔で出力を印刷します。

Ctrl+ Cを使用してプロセスを停止します。

の欠点はほとんどありません watch

  • エイリアスコマンドは使用できません。
  • コマンドの出力が非常に長い場合、スクロールは正しく機能しません。
  • 特定の値を超えて最大時間間隔を設定するには、いくつかの問題があります。
  • watch-cまたは--colorオプションを使用してエスケープ文字を渡すANSIカラーシーケンスを解釈します。たとえば、の出力pygmentizeは機能しls --color=autoますが、では失敗します。

上記の状況では、これがより良いオプションとして表示される場合があります。


watchそのために存在する、これは私が言うだろう少し役に立たないです
ブルーノペレイラ14年

14
私はこの答えが最初に使用されると主張しているわけではありません。watchほとんどの場合に適しています。だから、冒頭で「nuxの答えとは別に」と言ったのです。しかしwatch、たとえば、いくつかの問題がありますwatch。でエイリアスコマンドを使用することはできません。たとえばll、エイリアス化されているls -laFが、で使用することはできませんwatch。また、コマンドの出力が非常に長い場合、を使用してスクロールする際に問題が発生しwatchます。これらのいくつかの特別なケースでは、この答えがより良い選択肢に見えるかもしれません。
souravc 14年

@souravc watch少なくとも私のバージョンでは、色付き出力のオプション-cまたは--colorオプションが許可されています。
リリーチョン14年

8
while sleep xより良い-それは殺すのが簡単です。
d33tah 14年

3
これは優れた代替手段であり、とは異なりwatch、コマンド履歴を保持します。
アデルリオサンティアゴ

34

souravcnuxの答えを売り込みたかっただけです。

  1. 一方でwatchFreeBSD上で、たとえば、時計が「別のtty回線上のスヌープ」へのコマンドがある- Ubuntuで完璧に動作しますが、あなたはあなたの「UNIX-FUは」純粋になりたい場合はことを避けたいと思うかもしれません。
  2. while true; do command; sleep SECONDS; doneまた、警告があります-CTR + Cを使用してコマンドを殺すのは難しいかもしれません。あなたが好むかもしれませんwhile sleep SECONDS; do command; done-それは短いだけでなく、中断するのも簡単です。警告は、最初にスリープしてからコマンドを実行するためSECONDS、コマンドが最初に発生するまでしばらく待つ必要があるということです。

2
コメントではなく答えとして受け入れられることを願っています-ここで別の解決策を示したかったのですが、実際にはコメントを付けるとあまり注意が払われません。
d33tah 14年

あなたはどこに置いたか、なぜまさにそれは問題ではないsleepwhileループ?私はCtrlキー+ Cがループを破っていない、任意の違いを見つけることができませんでし瞬時に何があって。
デザート

@dessert:あなたが何から抜け出そうとしているのかに依存します。通常は、Ctrl + Cは自分を殺すcommandsleep、あなたが殺した場合にのみ破りますtrue
d33tah

11

cron定期的なコマンドの実行を可能にするデーモンの理想的なタスクのように聞こえます。crontab -eコマンドを実行して、ユーザーのcron構成の編集を開始します。そのフォーマットは、に記載されているのcrontab(5) 。基本的に、5つの時間関連のスペース区切りフィールドとそれに続くコマンドがあります。

The time and date fields are:

       field          allowed values
       -----          --------------
       minute         0-59
       hour           0-23
       day of month   1-31
       month          1-12 (or names, see below)
       day of week    0-7 (0 or 7 is Sunday, or use names)

たとえば、毎週火曜日の午前11時にPythonスクリプトを実行する場合:

0 11 * * 1 python ~/yourscript.py

のような、時間を置き換える特別な名前もいくつかあります@reboot。一時ディレクトリを作成する必要がある場合に非常に役立ちます。私のcrontabから(リストされているcrontab -l):

# Creates a temporary directory for ~/.distcc at boot
@reboot ln -sfn "$(mktemp -d "/tmp/distcc.XXXXXXXX")" "$HOME/.distcc"

4
質問は、ターミナルで何かを定期的に実行する方法を尋ねます。 cronターミナルではなく舞台裏で走る
北ブラッドリー14

5

あなたがファイルシステムを監視している場合、それinotifywaitは素晴らしいですし、確かにあなたのシステムの負荷を減らします。

例:

第一ターミナルのコマンドを入力します。

$ inotifywait .

次に、2番目のターミナルで、現在のディレクトリに影響するコマンド、

$ touch newfile

その後、元の端末でinotifywaitが起動してイベントを報告します

./ CREATE newfile2

またはループで

$ while true ; do inotifywait . ; done
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ DELETE newfile
Setting up watches.  
Watches established.
./ CREATE,ISDIR newdir
Setting up watches.  
Watches established.

ユーザーは、何のスクリプトをあなたに言っていない、と多分彼は何を監視したいいけない
NUX

3
スクリプトを書くように彼に言ったのではなく、特定のファイルシステムイベントを監視するためにループしている場合は、inotifywaitが便利であり、コマンドを繰り返すよりも少ないリソースを使用することを提案しました。私はしばしばコマンドラインでいくつかのコマンドを実行します。例えばgrep something InALogFile|less、それはスクリプトですか?
X Tian 14年

その良い答えは、よりシンプルに見えるように編集してみてください。
nux 14年

3
.コマンドを省略できないよりも簡単なこともあります。
X Tian 14年

@XTian、素晴らしいコマンドをありがとう。また-m、ループなしで継続的に監視するために追加できることをマニュアルページで確認しました。
yoniLavi 14

4

repeat次の手順を実行して、独自のコマンドを作成できます。ここにクレジット

まず、.bash_aliasesファイルを開きます。

$ xdg-open ~/.bash-aliases

次に、これらの行をファイルの下部に貼り付けて保存します。

repeat() {
n=$1
shift
while [ $(( n -= 1 )) -ge 0 ]
do
    "$@"
done
}

3番目に、ターミナルを閉じてから再度開くか、次のように入力します。

$ source ~/.bash_aliases

ほら!次のように使用できます。

$ repeat 5 echo Hello World !!!

または

$ repeat 5 ./myscript.sh

行xdg-open〜/ .bash-aliasesに小さなタイプミスがあります。xdg-open〜/ .bash_aliases(例:アンダースコア)
ssinfod

4

crontabを使用できます。コマンドcrontab -eを実行し、好みのテキストエディターで開き、この行を追加します

*/10 * * * *  /path-to-your-command

これにより、コマンドが10分ごとに実行されます

* */4 * * *  /path-to-your-command

これは、4時間ごとにコマンドを実行します

別の可能な解決策

$ ..some command...; for i in $(seq X); do $cmd; sleep Y; done

繰り返すX回。

繰り返すのを待つY時間。

例:

$ echo; for i in $(seq 5); do $cmd "This is echo number: $i"; sleep 1;done

なぜこれが改善されたのですか?コマンドを変数として保存することで、余分な不要なステップを追加しました。これは、i)入力を長くするii)パイプまたはリダイレクトなどを使用せずに、単純なコマンドのみを使用するように強制するだけです。
terdon

余分な変数を削除
-Maythux

3

上記で提案された「監視」アプローチに関する別の懸念は、プロセスが完了したときにのみ結果を表示することです。「date; sleep 58; date」は、59秒後にのみ2つの日付を表示します。4分間実行しているコンテンツをゆっくり起動すると、コンテンツの複数のページがゆっくり表示されますが、実際には表示されません。

一方、「while」アプローチの懸念は、タスクの期間を考慮に入れていないことです。

while true; do script_that_take_between_10s_to_50s.sh; sleep 50; done

これにより、スクリプトは1分ごとに実行され、1分40秒かかる場合があります。そのため、cronが1分ごとに実行できたとしても、ここでは実行できません。

そのため、シェルの出力を生成されたとおりに表示し、正確な要求時間を待つには、前後の時間を調べ、whileでループする必要があります。

何かのようなもの:

while ( true ); do
  echo Date starting `date`
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))`
  echo Before waiting `date`
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
  echo Done waiting `date`
done

これはこれを出力します:

ご覧のとおり、コマンドは1分ごとに実行されます。

Date starting Mon Dec 14 15:49:34 EST 2015
Before waiting Mon Dec 14 15:49:52 EST 2015
Done waiting Mon Dec 14 15:50:34 EST 2015

Date starting Mon Dec 14 15:50:34 EST 2015
Before waiting Mon Dec 14 15:50:39 EST 2015
Done waiting Mon Dec 14 15:51:34 EST 2015

そのため、「sleep echo $(( ( RANDOM % 30 ) + 1 ))」コマンドを、ターミナル/シェル上で正確に毎分実行されるものに置き換えてください。別のスケジュールが必要な場合は、必要なもので「60」秒を変更してください。

デバッグ行のない短いバージョン:

while ( true ); do
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))` # Place you command here
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
done

自分に返信する...コマンドに設定した遅延以上の時間がかかる場合、$ DELAYは負の値を取得し、sleepコマンドは失敗するため、スクリプトはすぐに再起動します。そのことに注意する必要があります。
jmspaggi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.