Script de transfert FTP avec limitation du trafic et purge

De Wiki de Romain RUDIGER
Aller à : navigation, rechercher

Scripts de transfert ftp avec wput ou lftp.

Script :

#!/bin/bash

# Variables d'environnement
Program="$(basename $0)"
DirBin=/scripts
DirLog=/var/log
DirTemp=/tmp
functions="${DirBin}/functions.sh"
# Sourcing des scripts utilises
if [[ ! -f ${functions} ]]; then
   echo "ERROR-Script ${functions} inacessible"
   exit 1
else
   source ${functions}
   [ $? -ne 0 ] && echo "ERROR-Impossible de sourcer ${functions}" && exit 1
fi

# Chargement des environnements
Start_Date=$(get_date)
Start_Time=$(date +%s)

# Get signterm
# Arret par l'utilisateur de l'execution du script
function handle_trap
{
   if [[ -z ${Log} ]]; then
      error_nolog "Arret du script par l'utilisateur ($1)!"
   else
      error "Arret du script force ($1)!"
   fi
   exit_script 1
}
trap "handle_trap SIGTERM" SIGINT SIGTERM

# Fonction Usage
function usage
{
   echo "Usage: ${Program} -serveurSrc=<serveur source> -dirBase=</test/> -files2transfer=<*DB*050511*> -fullFtpDest=<ftp://user:pwd@url:port/destination-dir/> [-limitRate=<bande passante xK ou xM>] [-purge=<0|1>] [-help]"
   echo "   serveurSrc : adresse du serveur source (connection en ssh)"
   echo "   dirBase : base des fichiers a transferees (cet arborescence n'est pas recree sur la destination)"
   echo "   files2transfer : fichiers a transferer depuis le serveur 'serveurSrc'"
   echo "   fullFtpDest : url ftp avec utilisateur et mot de passe ainsi que le dossier destination"
   echo " Parametres facultatifs :"
   echo "   [-limitRate] : permet de limiter la bande passante utilisee (soit en Mega octets 'M' ou en Kilo octets 'K')."
   echo "   [-purge=<0|1>] : 0 par defaut / 1 -> Suppr tous les fichiers existants sur le repertoire FTP distant"
   echo "   [-help] : affiche ce message"
   exit_script 1
}

function purge()
{
serveurSrc=$1
dirBase=$2
fullFtpDest=$3
FTP_USER=`echo $fullFtpDest | cut -c7-100 | awk -F[@:] '{print $1}'`
FTP_PASSWORD=`echo $fullFtpDest | cut -c7-100 | awk -F[@:] '{print $2}'`
FTP_SERVER=`echo $fullFtpDest | cut -c7-100 | awk -F[@:] '{print $3}'`
info "Debut purge du repertoire FTP de destination"
ftp -inv $FTP_SERVER <<EOT
user $FTP_USER $FTP_PASSWORD
mdelete *
bye
EOT
info "Fin purge du repertoire FTP de destination"
}

function f_purge() # FTP_SERVER=$1 FTP_USER=$2 FTP_PASSWORD=$3
{
info "Fonction f_purge: purge TOTALE du repertoire FTP de destination"
echo "ftp_srv= $1 / user= $2 / pass= $3"

ssh -T -o StrictHostKeyChecking=no $ServeurSrc << EOF 2>&1 | tee -a ${Log}

ftp -inv $1 <<EOT
user $2 $3
mdelete *
bye
EOT

EOF
info "Fonction f_purge: fin de la purge TOTALE du repertoire FTP de destination"
}

######################
# Traitement de la ligne de commande
######################
ServeurSrc=;DirBase=;files2transfer=;fullFtpDest=;limitRate=;purge=;
Purge=0; # par de purge par defaut
NbArgument=$#
Last_argument=${!NbArgument}

# Traitement des arguments
for arg in $*; do
   argVal=$(echo ${arg} | awk -F = '{print $2}')
   if [[ "${arg}" == "-help" ]]; then
      usage
   fi
   test_regExp "${arg}" "^-serveurSrc=.*$" && ServeurSrc=${argVal} && continue
   test_regExp "${arg}" "^-dirBase=.*$" && DirBase=${argVal} && continue
   test_regExp "${arg}" "^-files2transfer=.*$" && Files2transfer=${argVal} && continue
   test_regExp "${arg}" "^-fullFtpDest=.*$" && FullFtpDest=${argVal} && continue
   test_regExp "${arg}" "^-limitRate=.*$" && LimitRate=${argVal} && continue
   test_regExp "${arg}" "^-purge=.*$" && Purge=${argVal} && continue
   error_nolog "L'argument ${arg} n'est pas utilise par ce script."
done
# Test des arguments
[[ -z $ServeurSrc ]] && error_nolog "L'argument -serveurSrc est requis." && usage
[[ -z $Files2transfer ]] && error_nolog "L'argument -files2transfer est requis." && usage
[[ -z $FullFtpDest ]] && error_nolog "L'argument -fullFtpDest est requis." && usage
test_regExp "$DirBase" "^(|(/.+)*/)$"
[[ $? -ne 0 ]] && error_nolog "L'argument -dirBase n'est pas du bon format (^(|(/.+)/))$)" && usage
test_regExp "$FullFtpDest" "^ftp://.*:.*@.*:[[:digit:]]+/"
[[ $? -ne 0 ]] && error_nolog "L'argument -fullFtpDest n'est pas du bon format (^ftp://.*:.*@.*:[[:digit:]]+/)." && usage
test_regExp "$LimitRate" "^(|[[:digit:]]+(M|K))$"
[[ $? -ne 0 ]] && error_nolog "L'argument -limitRate n'est pas du bon format (^(|[[:digit:]]+(M|K))$)." && usage
#mna
test_regExp "$Purge" "^(|(0|1))$"
[[ $? -ne 0 ]] && error_nolog "L'argument -purge n'est pas du bon format (^(|(0|1))$)." && usage
# Log
Log=${DirLog}/replicat_${ServeurSrc}_$(echo "$Files2transfer" | sed -re "s/(\/|\*)/-/g")_${Start_Date}.log
# decoupage des variables pour utilisation de lftp
ftp_user=$(echo ${FullFtpDest} | awk -F: '{print $2}' | sed 's!//!!g')
ftp_pass=$(echo ${FullFtpDest} | awk -F: '{print $3}' | awk -F"@" '{print $1}')
ftp_srv=$(echo ${FullFtpDest} | awk -F: '{print $3}' | awk -F"@" '{print $2}')
ftp_port=$(echo ${FullFtpDest} | awk -F: '{print $4}' | awk -F "/" '{print $1}')
ftp_dir_dest=$(echo ${FullFtpDest} | awk -F: '{print $4}' | sed -r 's/^[0-9]{2,5}//g')
# calcul de la bande passante pour lftp en Octet/sec
LimitRate_suffix=${LimitRate: -1}
LimitRate_longeur_1=$((${#LimitRate} - 1))
LimitRate_valeur=${LimitRate:0:${LimitRate_longeur_1}}
lftp_LimitRate=500000; #valeur par defaut de lftp en upload soit 500kB/s
[[ "$LimitRate_suffix" = "M" ]] && lftp_LimitRate=$(($LimitRate_valeur * 1024 *1024 ))
[[ "$LimitRate_suffix" = "K" ]] && lftp_LimitRate=$(($LimitRate_valeur * 1024 ))

# Affiche les informations d'execution
info "Script execute : $0 $*"
info "Fichier de log : ${Log}"
format="\t%-20s %s\n"
print_var "ServeurSrc"
print_var "DirBase"
print_var "Files2transfer"
print_var "FullFtpDest"
print_var "ftp_user"
print_var "ftp_pass"
print_var "ftp_srv"
print_var "ftp_port"
print_var "ftp_dir_dest"
print_var "LimitRate"
print_var "lftp_LimitRate"
print_var "Purge"

ssh -T -o StrictHostKeyChecking=no $ServeurSrc << EOF 2>&1 | tee -a ${Log}
   . ${DirBin}/functions.sh
    if [[ -x /usr/bin/lftp ]]; then
            Cmde_Transfert="/usr/bin/lftp"; 
        else
            if [[ -x /usr/bin/wput ]]; then
                    Cmde_Transfert="/usr/bin/wput";
                else
                    error_nolog "/usr/bin/lftp et /usr/bin/wput ne sont PAS DISPOS sur la machine ${ServeurSrc} !";
                    exit 1;
            fi
    fi
   info_nolog "On utilisera le binaire de transfert: \${Cmde_Transfert}";
   info_nolog "Voici les fichiers qui seront transferes :"
   ls -la $Files2transfer
   return_status=\$?
   if [[ \$return_status -ne 0 ]]; then
      error_nolog "Impossible de lister les fichiers a transferer : \$return_status"
      exit \$return_status
   fi
   info_nolog "Lancement du transfert $([[ ! -z $LimitRate ]] && echo ", bande passante de $LimitRate "):"
   if [ "\${Cmde_Transfert}" == "/usr/bin/wput" ]
       then  
            \${Cmde_Transfert} --tries=5 $([[ ! -z $LimitRate ]] && echo "--limit-rate=$LimitRate") $([[ ! -z $DirBase ]] && echo "--basename=$DirBase") $Files2transfer $FullFtpDest
        else
            #lftp -e "lcd /tmp;mput ab*;quit" -u ftp_obieprd,crm-trans-prod -p 21 zdhqussibd1
            \${Cmde_Transfert} -d -e "set net:limit-rate 0:${lftp_LimitRate}; lcd ${DirBase}; mput ${Files2transfer}; quit;" -u ${ftp_user},${ftp_pass} -p ${ftp_port} ${ftp_srv}
            
    fi
    return_status=\$?
   if [[ \$return_status -ne 0 ]]; then
      error_nolog "La commande \${Cmde_Transfert} a retournee le code d'erreur : \$return_status"
      exit \$return_status
   fi
   info_nolog "La commande \${Cmde_Transfert} s'est bien terminee."
EOF
return_status=(${PIPESTATUS[@]})
remove_color_in_logfile
if [[ ${return_status[0]} -ne 0 ]]; then
   error "Probleme lors de la commande ssh (return=${return_status[0]})"
   exit_script ${return_status[0]}
fi

exit_script 0

functions.sh :

# Verification d'une expression reguliere
#
# Args : <valeur a tester> <expression reguliere>
#
# Exemple : test_regExp $VAR "^([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}$"
#  test si $VAR est une adresse IPv4, renvoie 0 si oui.
function test_regExp 
{
   Dest_OS="$(uname)"
   if [[ "${Dest_OS}" == "Linux" ]]; then
      grep_cmd="/bin/grep"
   elif [[ "${Dest_OS}" == "SunOS" ]]; then
      grep_cmd="/usr/xpg4/bin/grep"
   else
      grep_cmd="grep"
   fi
   echo "$1" | ${grep_cmd} -Eq "$2" > /dev/null
   return $?
}

# Obtenir la date
#
function get_date
{
   echo $(date +%Y%m%d-%H%M)
}

# Pour ecrire une erreur sur la sortie standard
#
# Arg : <Description de l'erreur>
#
# Exemple : error_nolog "Impossible de resoudre le nom d'hote."
function error_nolog
{
   echo -e "\E[31mERROR\E[37m-$(get_date)-$(hostname)-$1"
}

# Pour ecrire une erreur sur la sortie standard et dans le fichier de log
#
# Arg : <Description de l'erreur>
#
# Exemple : error "Impossible de resoudre le nom d'hote."
function error
{
   echo -e "\E[31mERROR\E[37m-$(get_date)-$(hostname)-$1"
   echo -e "ERROR-$(get_date)-$(hostname)-$1" >> ${Log}
}

# Pour ecrire une info sur la sortie standard
#
# Arg : <Description de l'information>
#
# Exemple : info_nolog "Debut du clonage..."
function info_nolog
{
   echo -e "\E[32mINFO\E[37m-$(get_date)-$(hostname)-$1"
}

# Pour ecrire une info sur la sortie standard et dans le fichier de log ${Log}
#
# Arg : <Description de l'information>
#
# Exemple : info "Debut du clonage..."
function info
{
   echo -e "\E[32mINFO\E[37m-$(get_date)-$(hostname)-$1"
   echo -e "INFO-$(get_date)-$(hostname)-$1" >> ${Log}
}

# Pour ecrire un warning sur la sortie standard
#
# Arg : <Description du warning>
#
# Exemple : warning_nolog "Attention..."
function warning_nolog
{
   echo -e "\E[33mWARNING\E[37m-$(get_date)-$(hostname)-$1"
}

# Pour ecrire un warning sur la sortie standard et dans le fichier de log ${Log}
#
# Arg : <Description du warning>
#
# Exemple : warning "Attention..."
function warning
{
   echo -e "\E[33mWARNING\E[37m-$(get_date)-$(hostname)-$1"
   echo -e "WARNING-$(get_date)-$(hostname)-$1" >> ${Log}
}

# Affiche une variable si elle est enrichie. Un espace est ajoute devant chaque majuscule.
#
# Arg : <nom de la variable>
#
# Exemble : print_var "HostSrc"
function print_var
{
   value="$(eval echo \${$1})"
   if [[ ! -z "$value" ]]; then
      [[ -z "$format" ]] && format="\t%-20s %s\n"
      desc="$(echo $1 | sed -re "s/[[:upper:]]+{1,2}/\ &/g" -e "s/\ \ /\ /g")"
      info "$(printf "$format" "$desc" ": $value")"
   fi
}

# Permet de supprimer la coloration des sorties info, info_nolog, error, error_nolog
#
# Exemple : remove_color_in_logfile
function remove_color_in_logfile
{
   sed -ri "s/\o33\[([[:digit:]]){2}m//g" ${Log}
}

# Termine le script en affichant le temps ecoulle
#
# Arg : <exit code>
#
# Global vars : ${Start_Time} ${Log}
#
# Exemple : exit_script 1
function exit_script
{
   # affichage du temps ecoulle
   if [[ ! -z $Start_Time ]]; then
      Duration_Time=$(expr $(date +%s) - $Start_Time)
      Duration_Time_Mn=$(expr $Duration_Time / 60)
      Duration_Time_Sec=$(expr $Duration_Time - \( $Duration_Time_Mn \* 60 \) )
      if [[ -z ${Log} ]]; then
         info_nolog "Duree du script : ${Duration_Time_Mn}m ${Duration_Time_Sec}s"
         info_nolog "Code retour du script : $1"
      else
         info "Duree du script : ${Duration_Time_Mn}m ${Duration_Time_Sec}s"
         info "Code retour du script : $1"
         info "Les logs du traitement sont dans le fichier : ${Log}"
         remove_color_in_logfile
      fi
   fi
   exit $1
}