2017-06-21 2 views
0

J'ai créé un script qui vérifiera l'existence des fichiers .gz dans le répertoire de base et s'il les trouve, il les déplacera dans une nouvelle structure basée sur la date actuelle. Le script fonctionne parfaitement quand le shell est défini sur/bin/bash et je l'exécute manuellement, mais ce script est exécuté comme un travail cron (par logrotate) et je crois qu'il DOIT être exécuté sous/bin/sh car je ne suis pas Assurez-vous d'avoir logrotate pour l'exécuter sous/bin/bash. Le code en question estVérifier si le fichier existe [SH]

# Move rotated logs to the archive 
if [ -f $BASEDIR/*.gz ]; then 
     logger "$SNAME Moving rotated logs to $DIRECTORY" 
     mv $BASEDIR/*.gz $DIRECTORY 
else 
     echo "$BASEDIR/*.gz" 
     logger "$SNAME No rotated logs to move. Is this normal?" 
fi 

En bash le chèque conditionnel fonctionne très bien, sous sh il se plaint, il y a trop d'arguments. Si je mets des choses entre guillemets, le caractère générique et les retours ne sont pas faux.

Toute aide serait fantastique!

+0

En aparté - noms en majuscules sont utilisés pour les variables ayant un sens à l'OS ou le shell, alors que les noms minuscules sont réservés à l'utilisation des applications. Voir le quatrième paragraphe de http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html –

+0

@CharlesDuffy, merci pour cette information, je n'ai jamais connu cette distinction et j'ai toujours utilisé toutes les majuscules pour les variables disponibles globalement. – hobbymaster001

Répondre

0

Le problème ici est que [ -f pathname ] prend exactement un nom ([ -f one.gz two.gz ] est pas valid test syntax), mais vous ne savez pas combien de noms *.gz se développe pour.

check() { 
    set -- "$BASEDIR"/*.gz 
    if [ -f "$1" ] || [ -L "$1" ]; then 
    logger "$SNAME Moving rotated logs to $DIRECTORY" 
    mv -- "[email protected]" "$DIRECTORY" 
    else 
    echo "$BASEDIR/*.gz" 
    logger "$SNAME No rotated logs to move. Is this normal?" 
    fi 
} 
check 

Briser ce bas:

  • check() { ... } définit une fonction nommée check, que nous appelons alors plus tard.
  • set -- "$BASEDIR"/*.gz remplace la liste d'arguments de la fonction (c'est pourquoi nous utilisons une fonction, donc nous ne remplaçons pas la liste d'arguments du script!) Avec une liste de fichiers dont le nom se termine par *.gz.
  • [ -f "$1" ] teste si le premier nom existe dans cette liste - si c'est le cas, alors nous savons que l'expansion a réussi. [ -L "$1" ] peut également être vrai si le glob a été développé avec succès mais la première entrée était un lien symbolique vers un fichier qui n'existe pas; en l'incluant, nous couvrons ce cas de coin.
  • mv -- "[email protected]" "$DIRECTORY" réutilise cette liste d'arguments pour passer à mv. L'argument -- spécifie à mv que tous les arguments suivants sont des noms, même s'ils commencent par - s.
+0

Merci beaucoup. Cela a fait l'affaire et tout fonctionne très bien! Je trouve intéressant que la limite de fichier unique ne soit pas un problème dans bash mais dans sh c'était un problème. – hobbymaster001

+0

Il est * un * problème dans bash aussi - Je me demande si vous n'avez peut-être pas plus d'un fichier prêt à être transféré lors de tests plus tôt? –

0

Que diriez-vous ceci:

if ls "$BASEDIR"/*.gz 
then 
    echo "moving them ..." 
else 
    echo "No such file!" 
fi 
+0

'si ls" $ BASEDRI "/ *. Gz &>/dev/null' ... – codeforester

+1

Ma réponse originale contenait aussi la suppression de la sortie, mais ensuite je l'ai enlevé à cause de la clarté et parce que j'avais le sentiment que OP pourrait vouloir avoir cette sortie, en fait. Dans l'autre cas, il y avait déjà un tel message, et je l'ai jugé utile dans le cas présent. Mais bien sûr, la suppression que vous avez proposée est la norme dans la plupart des cas. – Alfe