Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have a shell script to automate a git commit and push every night:

auto_git_push.sh

#!/bin/sh

function automate(){
    git add .
    git commit -am "automated push $(date +"%Y-%m-%d")"
    git push -u
}

cd ~/htdocs
automate

If I run this command, the script works as expected: . ~/bin/auto_git_push.sh

However, with this crontab line (set to every minute for testing)

* * * * * sh /home/hookedonwinter/bin/auto_git_push.sh

I get the following error:

/home/hookedonwinter/bin/auto_git_push.sh: 3: Syntax error: "(" unexpected

What is causing this syntax error?

Thanks!

Edit based on accepted answer:

Changed the script to:

#!/bin/bash

automate() {
    git add .
    git commit -am "automated push $(date +"%Y-%m-%d")"
    git push -u
}

cd ~/htdocs
automate

And the crontab line to:

* * * * * /bin/bash /home/hookedonwinter/bin/auto_git_push.sh

share|improve this question
add comment

3 Answers

up vote 1 down vote accepted

As John mentioned, it is a matter of your script being interpreted differently in the two environments (using /bin/sh under cron, and using your existing shell, which is probably /bin/bash when you source it in directly). Actually, /bin/sh is usually just a symlink to /bin/bash, and the bash executable behaves differently depending on the name under which it was invoked, but that's just an aside.

Here, the easiest way to fix your issue is probably just to specify

/bin/bash /home/hookedonwinter/bin/auto_git_push.sh

as the command to run under cron.

share|improve this answer
add comment

The cron environment is interpreting the inlined command differently than your shell environment. I'm guessing your shell is /bin/bash, which means it's running in a different shell entirely than it does in cron (the ". " construct reads the command stream into the shell, it doesn't invoke the shell in the shebang line). I'm not sure what syntax you need to use in /bin/sh, but I would start by trying simple backticks in place of the $( and ). Once you find something that works, you can either use it or continue searching for something more appealing to your aesthetics.

share|improve this answer
    
I started to work on this, and someone else (in real life proximity) suggested the same thing that @jjlin just did, which worked. Thanks! –  hookedonwinter Jan 30 '13 at 19:19
add comment

There are 2 different shells at work here. /bin/sh is the POSIX shell (syntax based on the Bourne shell). /bin/bash is the Bourne Again Shell, a.k.a. Bash. It is POSIX-compliant, but adds its own syntax, among other things. Depending on your system setup, /bin/sh could be a symlink to some other POSIX-compliant shell like dash or ash. The important point is that it expects POSIX shell syntax, without Bash extras.

In Bash scripting, functions can be declared with the function reserved word, which makes the parentheses optional. This means that in Bash, the following are all valid function declarations:

function foo() { true; }
function bar { true; }
baz() { true; }

But according to POSIX shell syntax, only the last one, baz() { true; }, is valid.

Based on the answer you've chosen to this question, you can see that invoking the script directly with /bin/bash will cause Bash to interpret your script, with no problems. For future reference, though, only use POSIX syntax in scripts that start with a #!/bin/sh shebang, and use #!/bin/bash for scripts that contain Bash-specific syntax.

share|improve this answer
    
Thanks for this clarification! –  hookedonwinter Jan 31 '13 at 16:01
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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