2015-01-08 18 views
6

mio script funziona se l'eseguo in modo interattivo sulla shell dei comandi:GNU parallela in script bash con "esportazione -f <func>" non riuscita con "command not found" errore quando crond

$ 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 

Ma, lo script non è riuscita e lamentato la funzione esportata, ndmpcopy_cron_parallel, non può essere trovato:

$ crontab -l 

40 0,2,4,6,8,10,12,14,16,18,20,22 * * * /u/jsung/bin/ndmpcopy_cron_parallel_svlinf05.bash 

Errore:

Subject: Cron <[email protected]> /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 

Sono stato perquisito e ho provato diverse cose per un po '. Ho persino ottimizzato $ PATH. Non so cosa mi sia perso. Possiamo incorporare GNU Parallel nello script BASH e inserire in crontab?

+0

Come è '/ bin/bash' diverso da '/ usr/software/bin/bash'? Sembra che il lavoro cron utilizzi '/ bin/bash'. Il tuo script funziona quando viene eseguito con '/ bin/bash'? –

+0

Giusto. Non molta differenza./usr/software/bin è dove la nostra azienda memorizza le utilità./bin/bash è il percorso predefinito con l'host. $/bin/bash --version GNU bash, la versione 4.1.2 (1) -release (x86_64-redhat-linux-gnu) Copyright (C) 2009 Free Software Foundation, Inc. licenza GPLv3 +: GNU GPL versione 3 o successiva $/usr/software/bin/bash --version GNU bash, versione 4.2.53 (1) -release (x86_64-sconosciuto -linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. Licenza GPLv3 +: GNU GPL versione 3 o successiva jsung8

+0

E si può eseguire il copione con '/ bin/bash' manualmente? (Sembra che dovrebbe funzionare in modo non corretto.) Non ho familiarità con 'parallel' potresti farlo eseguire uno script (e mettere quella funzione in uno script) invece di questo metodo env? –

risposta

7

Congratulazioni. Sei stato shell-shocked.

Hai due versioni di bash installato sul vostro sistema:

  • /bin/bash V4.1.2 Un bash senza patch più vecchio
  • /usr/software/bin/bash v4.2.53 A mezza età- bash, patchato contro Shellshock

L'ultimo numero nella versione bash tripla è il livello di patch. Il bug Shellshock ha coinvolto un numero di patch, ma quello rilevante è 4.1.14, 4.2.50 e 4.3.27. Questo cerotto cambia il formato delle funzioni esportate, con la conseguenza che:

  • se si esporta una funzione da una festa pre-Shellshock ad una festa post-Shellshock, verrà visualizzato un avviso e la funzione esportata saranno respinte .
  • Se si esporta una funzione da bash post-shellshock a una bash pre-shellshock, il formato di esportazione della funzione non verrà riconosciuto, quindi verrà ignorato in modo silenzioso.

In entrambi i casi, la funzione non verrà esportata. In altre parole, è possibile esportare una funzione tra due versioni bash solo se entrambe sono state sottoposte a patch shellshock o se non sono state applicate patch shellshock.

Lo script indica chiaramente quale bash utilizzare per eseguirlo: quello in/usr/software/bin/bash, che è stato corretto. Lo script invoca GNU parallel, e GNU parallel deve quindi avviare una o più subshell per eseguire i comandi. GNU parallel usa il valore della variabile di ambiente SHELL per trovare la shell che dovrebbe usare.

Suppongo che nel vostro ambiente di shell di comando dell'utente, SHELL è impostato su /usr/software/bin/bash, e che in un ambiente in cui cron esegue, esso è impostato su /bin/bash. Se questo è il caso, non avrai problemi ad esportare la funzione quando la proverai da un prompt di bash, ma nell'ambiente cron finirai per provare ad esportare una funzione da bash post-shellshock a una bash pre-shellshock, e come descritto sopra il risultato è che l'esportazione viene silenziosamente ignorata. Quindi l'errore.

Per aggirare il problema, è necessario assicurarsi di utilizzare lo bash utilizzato per eseguire lo script di comando è lo stesso di bash utilizzato da GNU parallelo. Ad esempio, è possibile impostare esplicitamente la shell prima di richiamare il parallelo GNU.

export SHELL=/usr/software/bin/bash 
# ... 
/u/jsung/bin/parallel -j 0 --wd . --env ndmpcopy_cron_parallel --eta ndmpcopy_cron_parallel ::: local 

Oppure si può semplicemente impostare per il comando in parallelo in sé:

SHELL=/usr/software/bin/bash /u/jsung/bin/parallel -j 0 --wd . --env ndmpcopy_cron_parallel --eta ndmpcopy_cron_parallel ::: local 
+0

rick e Ole, grazie mille per la tua opinione! shellshock è davvero la causa principale. Molto apprezzato!! L'unico trucco che ho trovato è che lo shellshock "/ bin/bash" è stato effettivamente attivato da crontab. Il lavoro di cron ha finalmente preso il via dopo aver aggiunto SHELL e PATH al mio crontab. Penso che SHELL sia richiesto nello script se distribuiamo il lavoro su host remoti. Per beneficiare gli altri ho riassunto le principali modifiche che ho fatto per il mio script e crontab nel commento successivo – jsung8

+0

cambiamenti nel mio script: export SHELL =/usr/software/bin/bash export -f ndmpcopy_cron_parallel /u/jsung/bin/parallelamente -j 0 --env SHELL --eta ndmpcopy_cron_parallel ::: locale Variazioni su crontab: SHELL =/usr/software/bin/bash PATH =/usr/software/bin:/u/jsung/bin – jsung8

2

Come rici dice, il problema è molto probabilmente dovuto a Shellshock. Shellshock non ha influenzato GNU Parallel, ma le patch per correggere shellshock hanno interrotto il trasferimento delle funzioni usando '--env'.

GNU Parallel sta recuperando le patch di shell in Bash: Bash ha utilizzato BASH_FUNC_myfunc() come nome di variabile per le funzioni di esportazione, ma le versioni più recenti utilizzano BASH_FUNC_myfunc%%. Quindi GNU Parallel ha bisogno di sapere questo quando si trasferisce una funzione.

La versione '()' è stata riparata nel 20141022 e la versione '%%' dovrebbe essere corretta nel 20150122. Dovrebbero funzionare in qualsiasi combinazione. Quindi il tuo Bash remoto non ha bisogno di essere patchato allo stesso modo del tuo Bash locale: GNU Parallel "farà la cosa giusta", e non c'è bisogno di cambiare il tuo codice.

Si deve sentire libero di testare la versione git in cui vengono fissati entrambi: git clone git: //git.savannah.gnu.org/parallel.git

+0

Ole, Grazie per il tuo consiglio su --env quindi ho usato "--env SHELL" per associare SHELL environ var con parallelo ... – jsung8