0

I am trying to get a cloud server (built from an image I have saved) to execute a script from a URL upon startup, but the script is not executing properly.

I used one of the answers from Execute bash script from URL to configure a curl script, and am executing that script via the @reboot directive in crontab (Ubuntu 14.04). My setup looks like this:

The script contains these commands:

user@cloud-server-01:~$ cat startup.sh
#! /bin/sh
/usr/bin/curl -s http://192.168.100.59/user/startup.sh.txt | bash /dev/stdin

I call the script via crontab:

user@cloud-server-01:~$ crontab -l
@reboot /home/user/startup.sh > startup.log 2>&1 &

If I manually execute the script from the command line using exactly the same command, it works fine. However, executing by crontab on startup, it seems to hang, and I see the following processes running:

user@cloud-server-01:~$ ps ux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
user      1287  0.0  0.1   4444   632 ?        S    19:17   0:00 /bin/sh /home/user/startup.sh
user      1290  0.0  0.7  89536  3536 ?        S    19:17   0:00 /usr/bin/curl -s http://192.168.100.59/user/startup.sh.txt
user      1291  0.0  0.2  12632  1196 ?        S    19:17   0:00 bash /dev/stdin

Am I missing something obvious in why the cron execution isn't giving me the same results as my command line?

EDIT:

Thanks Olof for the redirect on my troubleshooting. In fact, curl is executing, and if I wait long enough (several minutes) it appears to operate as desired. I suspect the problem is that the network interface and/or URL is not available when curl is initially called, and while it may poll for a connection, it probably backs off its polling interval. So the question now becomes, "How do I check whether I have a connection to this URL before calling curl?"

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63

2 Answers2

1

This is not a bash problem; your curl command is still running so bash is still running, waiting for curl to close the pipe that the bash shell is reading from.

To troubleshoot your curl invocation I would run it first without piping to bash to check that I get the output I expected.

Olof
  • 111
  • 5
  • something like `bash <(/usr/bin/curl -s http://192.168.100.59/user/startup.sh.txt)` ??? – PradyJord May 27 '14 at 20:06
  • @Jord, that is equivalent to the invocation in the question with a different (modern-shell-only) syntax. The OP was using /bin/sh to invoke curl and that may not be able to handle that syntax. – Olof May 27 '14 at 20:19
  • @Olof, thanks for the hint on where to look. I've got it working by throwing a 60-second sleep into the script to give the network a chance to get setup. Still looking for a better way to poll for network connectivity within my own script. – Daniel Widdis May 27 '14 at 20:58
  • 1
    My pleaseure, @DanielWiddis. Checking that something reponds is a sound idea. I would not bother with the check_online setting global variables and printing strings. Somthing like: `while ! nc -z $HOST 80 > /dev/null 2>&1; do sleep 5; done` would suffice, IMHO. – Olof May 28 '14 at 17:16
  • Sweet. I'll try that. I am not very familiar with bash syntax so I steal liberally from elsewhere on the internet! – Daniel Widdis May 28 '14 at 19:29
0

The hint in Olof's answer got me there, but I'm posting the full result here for completeness:

Because of a cloud provider's script which takes 20-40 seconds following reboot, my desired connection IP wasn't available to me when I first executed cron. It would either timeout, or connect after a significant delay. I have modified my connection script to poll the connection until it is available before calling curl:

#! /bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOST_IP=192.168.100.59

check_online() {
    IS_ONLINE=$(netcat -z -w 5 $HOST_IP 80 && echo 1 || echo 0)
}

# Initial check to see if we're online
check_online

# Loop while we're not online.
while [ $IS_ONLINE -eq 0 ];do
    # We're offline. Sleep for a bit, then check again
    sleep 5;
    check_online
done

# Run remote script
bash <(curl -s http://${HOST_IP}/user/startup.sh.txt)
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63