Continuously re-execute a command when it finishes in Bash

64

21

I'm trying to figure out a simple way to keep re-executing a command whenever it finishes, for any reason (error or otherwise).

What would be the best way to approach this?

EDIT: I wasn't clear enough before. I need the next execution to wait until the previous one finishes.

EDIT 2: Almost all answers work great. I mistakenly thought most answers would either fork the process or re-execute it just once, neither of which is wanted.

user107012

Posted 2011-11-27T11:41:12.420

Reputation:

1You still aren't clear. It'd help if you mentioned what program you're executing. – Daniel Beck – 2011-11-27T13:38:05.297

1-1 This question does not show any research effort, as the user commented that answers didn't work instead of actually trying to do what they suggest. – Daniel Beck – 2011-11-30T20:04:41.823

Answers

40

This creates an infinite loop, executing command over and over again.

while :
    do
        command
done

Dennis

Posted 2011-11-27T11:41:12.420

Reputation: 42 934

1

one line version: while true; do echo 'Hit CTRL+C'; sleep 1; done, thanks to https://www.cyberciti.biz/faq/bash-infinite-loop/

– jk2K – 2018-11-11T16:18:39.593

Please see the edit to the original question. I need to keep re-executing it over and over again, not just once. – None – 2011-11-27T13:31:29.560

8@calcifer This answer works quite well. There's something unusual about your program that none of the four users answering so far anticipated and you failed to mention it. – Daniel Beck – 2011-11-27T13:39:08.727

@calcifer this is an infinite loop. it keeps repeating until the end of time (well, until the script is terminated anyways) – Nate Koppenhaver – 2011-11-27T19:44:57.607

1My bad, I thought this (and all the other answers) will either fork the process or re-execute it just once, neither of which is wanted. So yes, this answer works. Thanks. – None – 2011-11-27T19:48:37.740

110

The watch command will repeat a command forever with an interval specified:

watch -n0 <command>

Setting -n to zero effectively puts the interval at nothing (I think it is really .1 seconds).

watch also has the added benefits of aligning the output so visual changes can be seen easily, and has a switch to highlight changes from the last run.

Reference: the watch man page:

watch runs command repeatedly, displaying its output (the first screenfull). This allows you to watch the program output change over time. By default, the program is run every 2 seconds; use -n or --interval to specify a different interval.

watch will run until interrupted.

Paul

Posted 2011-11-27T11:41:12.420

Reputation: 52 173

I can't see any output using this method. – Raffi Khatchadourian – 2016-03-08T01:37:47.417

@RaffiKhatchadourian Are you saying if you do watch ls in a directory that contains files, you don't get anything? – Paul – 2016-03-08T01:40:05.193

actually I was doing it with offlineimap. – Raffi Khatchadourian – 2016-03-08T03:08:00.560

@RaffiKhatchadourian So the approach works, you just don't get expected output from the specific thing you are doing. Sounds like a different problem – Paul – 2016-03-08T03:10:35.823

i dont see the continous output. so if i run watch echo 3 i am expecting to see a bunch of 3's printed but i only see one execution. – j2emanue – 2018-11-13T05:11:15.053

@j2emanue You are seeing multiple executions, but watch clears the screen each time. If you just want to loop a command, put a while loop around it. – Paul – 2018-11-13T05:12:58.993

@Paul your right. i just confirmed it. it keeps updating the same line. thanks – j2emanue – 2018-11-13T08:33:49.077

Please see the edit to the original question. – None – 2011-11-27T13:30:52.293

6All of the answers so far do this, including this one. Linux won't fork unless you specifically ask it to. – Paul – 2011-11-27T13:34:04.723

I didn't know that about fork, thanks. – None – 2011-11-27T19:54:30.817

17

A simple solution would be:

yourcommand; !#

; separates commands, allowing for multiple commands in one line (Bash: Lists)

!# tells bash to "repeat everything I have written so far in this line" (Bash: Event-Designators)

BlueSky

Posted 2011-11-27T11:41:12.420

Reputation: 171

Thanks for this, I was looking for it, especially since yourcommand; !! does not actually work with commands on the same line, however, !# seems to do. Cheers! – sdaau – 2015-01-25T21:11:09.673

; !# didn't work on ZSH, it just expands the statement essentially cloning it, it doesn't trigger it – revelt – 2018-03-05T13:43:09.807

1Sorry, I wasn't clear enough. I need to keep re-executing it over and over again, not just once. – None – 2011-11-27T13:27:11.037

7

You can plan ahead during command execution (provided it isn't interactive) and enter !! which will execute the previous command again. This works e.g. during ping -c 5.


You can also define a function in bash:

function repeat { "$@"; "$@"; }

To persist it, store it in ~/.bashrc.

Then, you can run your command like this:

repeat ping -c5 heise.de

If it's a specific command you want to repeatedly execute (and not e.g. any command), you can replace "$@" in that snippet with your actual command, and name the function e.g. repeat_ping instead.


To make it an infinite loop, you can do what @Dennis suggests. I recommend you add a waiting period if you intend to use this in an interactive shell, like this:

function repeat { while 1 ; do "$@" ; sleep 1 ; done; }

Otherwise it's rather inconvenient to abort this infinite loop using Ctrl-Z.

Daniel Beck

Posted 2011-11-27T11:41:12.420

Reputation: 98 421

Please see the edit to the original question. – None – 2011-11-27T13:30:46.693

6@calcifer These executions wait until the program call returns. Does your program detach from the shell and return before it quits? – Daniel Beck – 2011-11-27T13:31:52.577

My bad, I thought this (and all the other answers) will either fork the process or re-execute it just once, neither of which is wanted. So yes, this answer works. Thanks. – None – 2011-11-27T19:48:43.933

4

Give a while loop a boolean condition such as follows:

#!/bin/bash

while true; do

    do_something && wait

done

This will execute over and over until bash receives a signal to terminate the process. Usually in the form of ctrl+c.

You can also use the watch command to run a script repeatedly as well. For instance a simple clock in your bash terminal using watch could look like:

$ watch -t -n1 date +%T

The -t option tells watch to not display a title of the process it is running. This gives you a clean output of only the command that is being repeated. The -n1 option tells watch to repeat every n seconds. In this case, -n1 will be intervals of 1 second. Then the date +%T command shows the time at the time of command completion. Doing this command will give you an active clock in your terminal.

And then one more method that isn't in any of the other answers would be an infinite function call.

do_something() { do_something }; do_something && wait

This is essentially the same as the boolean while loop only using recursive function calls.

(edit) For keeping your machine's resources in mind, I have added the && wait so that each time a process is run, the loops will "wait" until that process finishes with exit status 0 before the next iteration. This is useful in an interactive shell script.

user723485

Posted 2011-11-27T11:41:12.420

Reputation:

1There is a while loop example but it isn't using a boolean true syntax. There is a watch example but it doesn't give many useful syntax. I am expounding on these for whomever it may help. I wanted to give some practical usefulness to these. The while loop boolean can also be false and not execute until an untrue condition is met. It is quite handy. – None – 2017-04-29T23:10:38.513

1@Spittin'IT Added a method that is not used in other answers for your convenience. – None – 2017-04-29T23:16:00.500

Fair enough and I understand... I was just commenting as I went thru the review module but nice edit and follow up!! – Pimp Juice IT – 2017-04-29T23:17:14.607

How does if keep re-executing? – Kamil Maciorowski – 2017-04-29T23:22:45.123

Good point Kamil. Forgot to make it recursive lol. Fixed in edit using a function calling itself in the if statement. – None – 2017-04-29T23:38:27.223

This if example seems over-complicated: (1) the if itself adds nothing and can be omitted; (2) the function does nothing more than calling itself. It's not clear where to put some custom code. How about run_me() { do_something; do_something_more; run_me; }; run_me? – Kamil Maciorowski – 2017-04-29T23:56:25.693

The if statement adds just another method. Nothing more, nothing less.The question asks for methods of recursion and they have been given. How practical or useful you might believe it is, or isn't, is irrelevant. – None – 2017-04-30T10:14:08.363

Because it seems an issue, I have removed the if statement and just added a recursive function call method instead. It is useful as I use it fairly often, personally, in my own scripts. – None – 2017-04-30T10:19:54.207

0

I'm feeling saucy today.

Read from one of the infinite streams and pipe it to xargs

cat /dev/zero | xargs --null echo hello there

If you need to put a little bit of a break in there you will likely need to execute sh

cat /dev/zero | xargs --null sh -c "echo hello there && sleep 3"

Jefferey Cave

Posted 2011-11-27T11:41:12.420

Reputation: 101

0

This is another method I use to repeat a command in bash. This might sound silly to some as it does not involve writing a script and might be known to many. But I think it is worth mentioning as it is quick and beginner-friendly, in the sense that there is not much syntax to remember. I've only tested this in gnome-terminal of Ubuntu and other terminals might not support this.

  1. Enter the command in terminal once.
  2. Select the command including newline character with mouse.
  3. Copy the selection using Ctrl-Insert or using context menu (usually accessed with right click).
  4. Use Shift-Insert to paste as many times as you want to run the command.

You don't have to wait to paste until each command finishes. The pasted commands get into a queue and they execute one after another.

jayadeepk

Posted 2011-11-27T11:41:12.420

Reputation: 11