My script works if I run it interactively on command shell:
$ cat ndmpcopy_cron_parallel_svlinf05.bash
#!/usr/software/bin/bash
ndmpcopy_cron_parallel() {
timestamp=`date +%Y%m%d-%H%M`
LOG=/x/eng/itarchives/ndmpcopylogs/05_$1/ndmpcopy_status
TSLOG=${LOG}_$timestamp
src_filer='svlinf05'
src_account='ndmp'
src_passwd='src_passwd'
dst_svm='svlinfsrc'
dst_account='vsadmin-backup'
dst_passwd='dst_passwd'
host=`hostname`
echo $host
ssh -l root $src_filer "priv set -q diag ; ndmpcopy -sa $src_account:$src_passwd -da $dst_account:$dst_passwd -i $src_filer.eng.netapp.com:/vol/$1 10.56.10.161:/$dst_svm/$1" | tee -a $TSLOG
echo "ndmpcopy Completed: `date` "
}
export -f ndmpcopy_cron_parallel
/u/jsung/bin/parallel -j 0 --wd . --env ndmpcopy_cron_parallel --eta ndmpcopy_cron_parallel ::: local
But, the script failed and complained the exported function, ndmpcopy_cron_parallel, cannot be found:
$ crontab -l
40 0,2,4,6,8,10,12,14,16,18,20,22 * * * /u/jsung/bin/ndmpcopy_cron_parallel_svlinf05.bash
Subject: Cron <jsung@cycrh6svl18> /u/jsung/bin/ndmpcopy_cron_parallel_svlinf05.bash
Computers / CPU cores / Max jobs to run
1:local / 2 / 1
Computer:jobs running/jobs completed/%of started jobs/Average seconds to complete
ETA: 0s Left: 1 AVG: 0.00s local:1/0/100%/0.0s **/bin/bash: ndmpcopy_cron_parallel: command not found**
ETA: 0s Left: 0 AVG: 0.00s local:0/1/100%/0.0s
I've been searched around and trying different things for a while. I even tweaked $PATH. Not sure what I missed. Can we embed GNU Parallel in BASH script and put in crontab at all?
Congratulations. You've been shell-shocked.
You have two versions of bash
installed on your system:
The last number in the bash version triple is the patch-level. The Shellshock bug involved a number of patches, but the relevant one is 4.1.14, 4.2.50 and 4.3.27. That patch changes the format of exported functions, with the consequence that:
In both cases, the function will not be exported. In other words, you can only export a function between two bash versions if they have both been shellshock patched, or if neither have been shellshock patched.
Your script clearly indicates which bash to use to run it: the one in /usr/software/bin/bash, which has been patched. The script invokes GNU parallel, and GNU parallel then has to start up one or more subshells in order to run the commands. GNU parallel uses the value of the SHELL
environment variable to find the shell it should use.
I suppose that in your user command shell environment, SHELL
is set to /usr/software/bin/bash
, and that in the environment in which cron
executes, it is set to /bin/bash
. If that's the case, you'll have no problems exporting the function when you try it from a bash prompt, but in the cron
environment you will end up trying to export a function from a post-shellshock bash to a pre-shellshock bash, and as described above the result is that the export is silently ignored. Hence the error.
To get around the problem, you need to ensure that you use the bash
used to run the command script is the same as the bash
used by GNU parallel. You could, for example, explicitly set the shell prior to invoking GNU parallel.
export SHELL=/usr/software/bin/bash
# ...
/u/jsung/bin/parallel -j 0 --wd . --env ndmpcopy_cron_parallel --eta ndmpcopy_cron_parallel ::: local
Or you could just set it for the parallel command itself:
SHELL=/usr/software/bin/bash /u/jsung/bin/parallel -j 0 --wd . --env ndmpcopy_cron_parallel --eta ndmpcopy_cron_parallel ::: local
As rici says, the problem is most likely due to shellshock. Shellshock did not affect GNU Parallel, but the patches to fix shellshock broke transferring of functions using '--env'.
GNU Parallel is catching up with the shellshock patches in Bash: Bash has used BASH_FUNC_myfunc()
as the variable name for exporting functions, but more recent versions use BASH_FUNC_myfunc%%
. So GNU Parallel needs to know this when transferring a function.
The '()' version is fixed in 20141022, and the '%%' version is expected to be fixed in 20150122. They should work in any combination. So your remote Bash does not need to be patched the same way as your local Bash: GNU Parallel will "do the right thing", and there is no need to change your own code.
You should feel free to test out the git version in which both are fixed: git clone git://git.savannah.gnu.org/parallel.git
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With