31

I would like to create a loop that repeats a ncftp transfer if it returns an error.

I'm a little unsure how the exit code variable can be used in a loop. Would something like this work?

until [$? == 0]; do
    ncftpput -DD -z -u user -p password remoteserver /remote/dir /local/file
done
1
53

I found the basis for this elegant loop elsewhere on serverfault. Turns out there is no need save the exit code, as you can test directly on the command itself;

until ncftpput -DD -z -u user -p password remoteserver /remote/dir /local/file; do
  echo Tansfer disrupted, retrying in 10 seconds...
  sleep 10
done
1
  • 1
    Oneliner: until command; do :; done – pbies Dec 23 '20 at 14:00
11

Almost. You are probably better saving the return value as a variable so that you can pre-set it before the loop. Otherwise it will be affected by the last-run command.

You might also want to sling a sleep in there to stop it respawning too quickly.

RET=1
until [ ${RET} -eq 0 ]; do
    ncftpput -DD -z -u user -p password remoteserver /remote/dir /local/file
    RET=$?
    sleep 10
done
6
  • I think forgot to pass the exit code to the RET variable, but I get the idea. My main question is when will the until clause be evaluated? In C it won't be evaluated until after the first run of the loop, in which case my loop should work. Yours is still better, though, as it allows for intermediate commands such as the sleep. Thanks! – Roy Nov 3 '09 at 9:33
  • Well spotted. I've edited it. The clause will be evaluated before the first run. So previously it would use the return code of any preceding command. The double-equals aren't enforced by Bash but it makes good practice to use. – Dan Carley Nov 3 '09 at 9:51
  • == is for string equality not numeric, although I don't think it matters in this case... – Kyle Brandt Nov 3 '09 at 13:01
  • Single and double equals are the same. But it would be better to use integer equality now that you mention it. – Dan Carley Nov 3 '09 at 13:33
  • 1
    You don't need to test the return code number -- you can just test the return code of the program itself -- until program ; do sleep 3 ; done . – chris Nov 3 '09 at 22:15
5

Bit hacky but my solution was to just create a bash function which runs itself if it exits with a failure

function retry { the_command_you_want && echo "success" || (echo "fail" && retry) }; retry
0

You can do a loop while your command returns error:

    while [ -n $(ncftpput -DD -z -u user -p password remoteserver /remote/dir /local/file) ]; do
            sleep 1;
    done;
2
  • 3
    This answer needs explanation. – kasperd Dec 9 '16 at 21:51
  • @kasperd explanation added – Andrés Rivas Dec 12 '16 at 15:59
0

I've had a similar problem with needing to repeat curl requests, and the scripting was getting out of hand. As a result I created the retry tool:

retry ncftpput -DD -z -u user -p password remoteserver /remote/dir /local/file

In this case, the ncftpput command will be retried indefinitely until it returns a success status code, backing off by default for ten seconds in between.

Retry is available here: https://github.com/minfrin/retry

0

Some of the solutions shown on this page will loop an infinite number of times if the command continues to fail.

If you're not a fan of infinite loops try this:

function retry {
    command="$*"
    retval=1
    attempt=1
    until [[ $retval -eq 0 ]] || [[ $attempt -gt 5 ]]; do
        # Execute inside of a subshell in case parent
        # script is running with "set -e"
        (
            set +e
            $command
        )
        retval=$?
        attempt=$(( $attempt + 1 ))
        if [[ $retval -ne 0 ]]; then
            # If there was an error wait 10 seconds
            sleep 10
        fi
    done
    if [[ $retval -ne 0 ]] && [[ $attempt -gt 5 ]]; then
        # Something is fubar, go ahead and exit
        exit $retval
    fi
}

Now, whenever you need a retry loop, just run:

retry mycommand and args

e.g.:

retry ncftpput -DD -z -u user -p password remoteserver /remote/dir /local/file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.