1

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

3 Answers 3

5

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.

1
  • Or you can set SHELL variable in the crontab file (if you are using debian) to SHELL=/bin/bash
    – racic
    Apr 5, 2017 at 13:42
2

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.

1
  • I started to work on this, and someone else (in real life proximity) suggested the same thing that @jjlin just did, which worked. Thanks! Jan 30, 2013 at 19:19
1

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.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .