web-dev-qa-db-fra.com

Le script Bash s'exécute manuellement, mais échoue sous crontab

Je suis un débutant dans les scripts Shell. J'ai écrit un script Shell pour effectuer une sauvegarde incrémentielle de la base de données MySQL. Le script est au format exécutable et s'exécute correctement lorsqu'il est exécuté manuellement, mais échoue lorsqu'il est exécuté via crontab. 

L'entrée Crontab est comme ceci:

*/1 * * * * /home/db-backup/mysqlbackup.sh

Vous trouverez ci-dessous le code de script Shell -

#!/bin/sh
MyUSER="root"       # USERNAME
MyPASS="password"         # PASSWORD
MyHOST="localhost"  # Hostname
Password="" #Linux Password

MYSQL="$(which mysql)"
if [ -z "$MYSQL" ]; then
echo "Error: MYSQL not found"
exit 1
fi
MYSQLADMIN="$(which mysqladmin)"
if [ -z "$MYSQLADMIN" ]; then
    echo "Error: MYSQLADMIN not found"
    exit 1
fi
CHOWN="$(which chown)"
if [ -z "$CHOWN" ]; then
    echo "Error: CHOWN not found"
    exit 1
fi
CHMOD="$(which chmod)"
if [ -z "$CHMOD" ]; then
    echo "Error: CHMOD not found"
    exit 1
fi

GZIP="$(which gzip)"
if [ -z "$GZIP" ]; then
    echo "Error: GZIP not found"
    exit 1
fi
CP="$(which cp)"
if [ -z "$CP" ]; then
    echo "Error: CP not found"
    exit 1
fi
MV="$(which mv)"
if [ -z "$MV" ]; then
    echo "Error: MV not found"
    exit 1
fi
RM="$(which rm)"
if [ -z "$RM" ]; then
    echo "Error: RM not found"
    exit 1
fi
RSYNC="$(which rsync)"
if [ -z "$RSYNC" ]; then
    echo "Error: RSYNC not found"
    exit 1
fi

MYSQLBINLOG="$(which mysqlbinlog)"
if [ -z "$MYSQLBINLOG" ]; then
    echo "Error: MYSQLBINLOG not found"
    exit 1
fi
# Get data in dd-mm-yyyy format
NOW="$(date +"%d-%m-%Y-%T")"

DEST="/home/db-backup"
mkdir $DEST/Increment_backup.$NOW
LATEST=$DEST/Increment_backup.$NOW
$MYSQLADMIN -u$MyUSER -p$MyPASS flush-logs
newestlog=`ls -d /usr/local/mysql/data/mysql-bin.?????? | sed 's/^.*\.//' | sort -g | tail -n 1`
echo $newestlog
for file in `ls /usr/local/mysql/data/mysql-bin.??????`
do
        if [ "/usr/local/mysql/data/mysql-bin.$newestlog" != "$file" ]; then
     echo $file             
     $CP "$file" $LATEST         
        fi
done
for file1 in `ls $LATEST/mysql-bin.??????`
do
 $MYSQLBINLOG $file1>$file1.$NOW.sql 
 $GZIP -9 "$file1.$NOW.sql"     
 $RM "$file1"
done
$RSYNC -avz $LATEST /home/rsync-back
  • Tout d’abord, lorsqu’il est programmé sur crontab, il ne montre aucune erreur. Comment puis-je savoir si le script est en cours d'exécution ou non?
  • Deuxièmement, quelle est la bonne façon d’exécuter le script Shell dans une crontab . Certains blogs suggèrent de modifier les variables d’environnement. Quelle serait la meilleure solution

Quand j'ai fait $ echo PATH, j'ai eu ceci 

/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/mysql/bin:/opt/Android-sdk-linux/tools:/opt/Android-sdk-linux/platform-tools:~/usr/lib/jvm/jdk-6/bin
13
Rudra

Le problème est probablement que votre $ PATH est différent dans l'environnement manuel de celui sous lequel crontab est exécuté. Par conséquent, which ne peut pas trouver vos exécutables. Pour résoudre ce problème, commencez par imprimer votre chemin dans l'environnement manuel (echo $PATH), puis configurez manuellement PATH en haut du script que vous exécutez dans crontab. Ou tout simplement faire référence aux programmes par leur chemin complet.

Edit: Ajoutez ceci près du haut de votre script, avant tous les appels which:

export PATH="/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/mysql/bin:/opt/Android-sdk-linux/tools:/opt/Android-sdk-linux/platform-tools:~/usr/lib/jvm/jdk-6/bin"
15
amaurea

Une autre méthode plus générique consiste à faire exécuter par cron le processus de connexion bash de l'utilisateur. En plus du PATH, cela récupérera également les paramètres LD_LIBRARY_PATH, LANG, les autres variables d’environnement, etc.

34  12  * * *   bash -l /home/db-backup/mysqlbackup.sh
11
JimR

Mon problème était que je définisse le travail cron dans /etc/cron.d (Centos 7). Il semble que, dans ce cas, je dois spécifier l'utilisateur qui exécute le script, contrairement à la saisie d'un cronjob au niveau de l'utilisateur. 

Tout ce que je devais faire était 

*/1 * * * * root Perl /path/to/my/script.sh
*/5 * * * * root php /path/to/my/script.php

Où "root" indique que j'exécute le script en tant que root . Vous devez également vous assurer que les éléments suivants sont définis en haut du fichier. Vos chemins peuvent être différents. Si vous n'êtes pas sûr, essayez la commande "quel Perl", "quel php".

Shell=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
4
blokeish

Importez simplement votre profil d'utilisateur au début du script.

c'est à dire.:

. /home/user/.profile
1
Enio Marques Junior