banneer

Réducteur d'URL tinad:

Collez l'adresse du site:

Rechercher sur le blog du grouik:

Catégorie: Informatique › scripts shell bash

Fil des billets - Fil des commentaires

Ce mémo a pour objectif d'expliquer comment automatiser le transfert d'un fichier par FTP. Pratique lors de la création de passerelles.

Prérequis: un serveur FTP. Le compte FTP utilisé est chrooté dans le dossier dans lequel doivent être déposés les fichiers. Pour créer le serveur FTP, ce billet donne la solution.

Pour le moment, on va faire un truc simplissime:

Je crée 3 fichiers scriptFTP.jpeg

  • script.bat est le script qui lancera le transfert. Il sera mis en tâches planifiées (pour ça, je vous laisse trouver comment on fait)
  • plannings_Extranet.ftp est la liste de commandes à éxécuter en FTP pour basculer les fichiers vers le repertoire FTP. Vous l'avez compris, la petite passerelle que je suis en train de faire a pour but de basculer les planings sur notre extranet.
  • Plop.txt est le fichier qui sera transféré; C'est juste pour le test hein!

script.bat

Il contient juste une ligne pour le moment.

  1. ftp -s:planings_Extranet.ftp

Il lance le client dos ftp, qui prendra la liste d'instructions contenues dans le fichier planings_Extranet.ftp

planings_Extranet.ftp

  1. open 192.168.10.253
  2. user
  3. password
  4. prompt
  5. lcd D:\testFtp
  6. put plop.txt
  7. quit

Explication ligne par ligne:

  • 1 Ouvrir la connexion vers le serveur 192.168.10.253
  • 2 Lui indiquer l'user FTP
  • 3 Lui indiquer le mot de passe ftp
  • 4 Attendre le prompt
  • 5 Se placer localement dans le repertoire comprenant le(s) fichiers à transférer
  • 6 envoyer le fichier
  • 7 fermer la connexion

plop.txt

Bah, c'est le fichier à transférer; OSEF?

Lancez script.bat, vérifiez sur le serveur de destination si le fichier a bien été poussé.

Un peu plus compliqué; On va pousser tous les fichiers d'un répertoire et créer un fichier de logs.

Prérequis, télécharger curl

Pour se simplifier un peu la vie, cette fois, on va utiliser curl. Téléchargez l'éxécutable qui correspond à votre version de windows: http://curl.haxx.se/download.html Je me créé l'architecture suivante sur le windows;

  • testFtp
    • script.bat
    • bin
      • curl.exe
      • license_curl.txt
    • toSend
      • fichier1.pdf
      • fichier2.pdf
      • fichier3.pdf

l'objectif est d'envoyer les fichiers (quelque soient leur noms) du dossier toSend sur notre ftp. Par contre si le fichier existe déja sur le serveur; je l'écrase.

Transfert automatique en écrasant les éventuels fichiers sur le serveur

Voici le contenu du scrip.bat

  1. ::Envoie le contenu d un repertoire sur un dossier FTP. Ecrase les fichiers déja existants si des noms sont concordants
  2. ::Ce script utilise Curl (pour le ftp). La licence se situe dans le dossier bin
  3. cls
  4. ::On met un titre au shell
  5. @title Envoie le contenu d un repertoire sur un dossier FTP. Ecrase les fichiers déja existants si des noms sont concordants
  6. ::Supprimer les retours écran
  7. @echo off
  8.  
  9. ::#### VARIABLES####
  10. ::PARTIE FTP
  11. set user_ftp=userFtP
  12. set pwd_ftp=pwdFtp
  13. set ip_ftp=192.168.10.253
  14. set path_ftp=/
  15. ::DOSSIER LOCAL A TRANSFERER
  16. set local_path=%cd%\toSend
  17.  
  18. ::Définition des Chemins
  19. ::répertoire racine
  20. set rep_root=%cd%
  21. ::chemin des binaires
  22. set rep_bin=%cd%\bin
  23. ::chemin des fichiers de journaux
  24. set rep_log=%cd%\log
  25.  
  26. ::Si le ping est négatif, quitter et logguer
  27. ping -n 1 %ip_ftp%
  28. if %errorlevel%==1 goto NO_LINK_SERV
  29.  
  30. ::On envoie
  31. cd %local_path%
  32. ::Eventuellement, remplacez *.* par le filtre de votre choix genre planing-*.pdf dans la partie qui suit
  33. if exist ./*.* (
  34. FOR %%f IN (*.*) DO (
  35. ::Envoi de chaque fichier sur le ftp
  36. %rep_bin%\curl.exe -u %user_ftp%:%pwd_ftp% -Q "+CWD %path_ftp%" -T "%%f" ftp://%ip_ftp%/
  37. ::On logue les infos dans un fichier
  38. echo "%date%|%time:~0,2%h%time:~3,2% : fichier %%f -- envoyé " >>%rep_log%/envois.log
  39. )
  40. ::On supprime les fichiers après l envoi car on en a plus besoin
  41. del/Q *.*)
  42. GOTO FIN
  43.  
  44. :NO_LINK_SERV
  45. ::le serveur ne répond pas au ping
  46. echo "%date%|%time:~0,2%h%time:~3,2% : Le serveur FTP n'est pas joignable - Aucun transfert effectué" >>%rep_log%/connexions.log
  47.  
  48. :FIN
  49. ::On quitte

Plus qu'à mettre le script dans les tâches planifiées.


EDIT dans les commentaires, Ben propose une solution en une ligne de code avec une regex:D

J'ai une base de donnée mal foutue (spamoi qui l'ai conçue) dans laquelle les noms et prénoms sont dans le même champs. Une typographie est respectée, toutes les lettres du nom sont en majuscules tandis que seule la première lettre de chaque prénom l'est. Plus dur, il n'y a pas de tiret, les noms ou prénoms composés sont séparés par des espaces.

Dans la base de données contenant plus d'un millier d’identités, il n'est jamais arrivé qu'un nom de famille ait trois composantes. Maximum deux. C'est pour ça que par flegme je me suis arrêté à cette possibilité dans l'algo ci dessous.

C'est la quatrième fois en 3 ans que je suis amené à travailler sur une passerelle où cette mauvaise conception me gonfle fortement.

  • la première fois, en java, compilé, j'ai paumé la source du truc.
  • Refait en Vb6 pareil, pareil, un code de moins de 50 lignes, on se fiche un peu de devoir le refaire.
  • Refait en vb6 cette fois, j'ai retrouvé la source
  • Là c'est en php que ça m'intéresse de le faire.

Ça n'a pas trop d’intérêt mais comme ce n'est peut être pas la dernière fois que j'ai à me pencher sur ce problème, je garde les algos sur ce blog:

En PHP

  1. function separenomprenom($stringname)
  2. {
  3. /*
  4. *NomPac
  5.   * Il est sous cette forme: 'NOM Prenom' voire
  6.   * 'NOM COMPOSE Prenom' ou encore
  7.   * 'NOM Prenom composé'
  8.   *On va spliter les espaces. Si on obtient deux champs on est dans le cas 1
  9.   *pour distinguer les autres cas on va tester la deuxième lettre
  10.   *pour savoir si elle est en majuscules.
  11. */
  12. $nomexplode=explode(" ",$stringname);
  13. if (count($nomexplode)==2)
  14. { //NOM Prénom
  15. return array('nom'=>$nomexplode[0],'prenom'=>$nomexplode[1]);
  16. }
  17. else
  18. {
  19. //test sur la deuxieme lettre du second mot
  20. if(preg_match_all('/[A-Z]/', substr($nomexplode[1],1,1),$res)==1)
  21. { //NOM NOM2 Prénom
  22. $prenom="";
  23. for($i=2; $i<count($nomexplode)+1;$i++)
  24. {
  25. $prenom = $prenom.$nomexplode[$i]." ";
  26. }
  27. return array('nom'=>$nomexplode[0]." ".$nomexplode[1],'prenom'=>$prenom);
  28. }
  29. else
  30. { //NOM Prénom Prénom2
  31. $prenom="";
  32. for($i=1; $i<count($nomexplode)+1;$i++)
  33. {
  34. $prenom = $prenom.$nomexplode[$i]." ";
  35. return array('nom'=>$nomexplode[0],'prenom'=>$prenom);
  36. }
  37. }
  38. }
  39. }

En basic

J'ai testé le script php sur plusieurs centaines de noms, mais pas le basic que je viens de modifier pour qu'il soit lisible retiré du script global (il peut y avoir une erreur qui traine).

  1. 'NomPac
  2. ' Il est sous cette forme: 'NOM Prenom' voire
  3. ' 'NOM COMPOSE Prenom' ou encore
  4. 'NOM Prenom composé'
  5. 'On va spliter les espaces. Si on obtient deux champs on est dans le cas 1
  6. 'pour distinguer les autres cas on va tester la deuxième lettre
  7. 'pour savoir si elle est en majuscules.
  8.  
  9.  
  10. nomsplit() = Split(NomPac, " ")
  11. If UBound(nomsplit(), 1) = 1 Then
  12. 'nom Prénom
  13. nom = nomsplit(0)
  14. prenom= nomsplit(1)
  15. Else
  16. 'test sur la deuxieme lettre du second mot
  17. If Asc(Mid(nomsplit(1), 2, 1)) < 91 Then 'c'est une majuscule donc la suite du nom de famille
  18. nom = nomsplit(0) & " " & nomsplit(1)
  19. prenom = ""
  20. For i = 2 To UBound(nomsplit(), 1)
  21. prenom = prenom & nomsplit(i) & " "
  22. Next i
  23. Else
  24. nom = nomsplit(0)
  25. prenom =""
  26. For i = 2 To UBound(nomsplit(), 1)
  27. prenom = prenom & nomsplit(i) & " "
  28. Next i
  29. End If
  30. End If


Il y a déjà un an ou deux, j'avais fait une passerelle avec notre logiciel de dossier de soins. J'avais utilisé comme point d'entrée l'interface de laboratoire (format HPRIM). Oui avec un logiciel propriétaire et fermé, plus que bancal, il faut bien trouver des moyens de faire des interfaces (sans solliciter leur service développement).

Les messages avant cryptage sont organisés selon un document norminatif HPRIM 1, que j'avais récupéré. Ne l'ayant plus, j'ai eu du mal à le retrouver (il est réservé aux adhérents). je me permet une citation de ce document, car c'est la partie que j'ai eu du mal à retrouver, et je pense que ça me resservira.

la "zone d’identification du patient" qui comprend 12 lignes :

  1. code patient facultatif
  2. Nom du patient
  3. Prénom du patient
  4. Premiere ligne de l adresse du patient
  5. deuxième ligne de l adresse du patient
  6. code postal sur 5 caracteres, un espace puis la ville
  7. date de naissance du patient JJ/MM/AAA
  8. code de sécurité sociale sur 13 caracteres espace puis extension du numéro
  9. Numéro de dossier
  10. Date du dossier au format JJ/MM/AAAA
  11. Code correspondant sur 10 caracteres, espace puis nom du correspondant
  12. Code prescripteur sur 10 caracteres espace puis nom du prescripteur

[source]


cmd.jpg Nous allons voir comment purger un dossier avec un script .bat (pour windaube quoi)

Bon okie, j'ai honte d'écrire ce billet. Mais faut me comprendre, cette semaine, j'ai installé des PC, modifié le script d'interface laboratoire, tellement spécifique qu'il n'y a aucun intérêt à en faire un billet. j'ai ajouté une fonction de petites annonces à notre intranet. Ce code est sans grand intéret aussi, juste un appel mysql en PHP. Ça m'embêtait de ne poster que des conneries, et encore plus ne rien poster. Alors, même si c'est tout simple, le code batch pour purger un repertoire, c'est:

@echo off
ECHO O | DEL D:\INTRANETG\INTRANET\scanner\*.*

"Echo O" retourne "O" lorsque le DOS demande confirmation, dans une version anglaise il aurait fallu "echo Y".

Vous l'aurez compris, le dossier scanner, qui reçoit les éléments scannés, mais qui par soucis de configuration est accessible à tout le monde contient plein de trucs confidentiels. Gênant. Ce script est en tâche planifiée tous les soirs pour compenser.


Fonctionnement

Le laboratoire avec qui on traite crypte les résultats de laboratoires avec des clés personnelles, les envoie à Apirypt (notre tiers de confiance) qui les décrypte, les recrypte avec nos clés avant de nous les envoyer (sur une BAL dédiée à ça).

Apicrypt propose facilement deux solutions:

  • on utilise ou paramètre un client mail (dans ce cas c'est manuel)
  • on ajoute leur "proxy" mail dans le lan. là c'est surtout adapté quand on a plusieurs services et plusieurs boites aux lettres pour les résultats de laboratoire.

La première solution est chiante car manuelle. Le seconde fait ajouter un élément dans le réseau pour pas grand chose.

Mais comme ils distribuent l'appli codée en C [1] qui peut décrypter depuis un système UNIX, profitons en.

Mon serveur de mails marche au format maildir, ça me permet de séparer simplement les mails.

Vous verrez, à une étape, le message transite en clair sur le serveur où se trouve l'application de dossier de soins. Je précise que le serveur de mails est sur la passerelle et que cette étape se fait via la carte réseau dans le lan, dans une DMZ. De plus physiquement les deux machines sont branchées sur le même switch, ce qui rendra difficile un sniffage tant que le cache d'adresses mac du répartiteur n'est pas en faute.

Monter le dossier dans lequel seront déposés les résultats de laboratoire.

Editer le fichier /etc/fstab et y ajouter la ligne suivante:

//IP-du-serveur/applic$  /media/applic cifs user,rw,username=USERNAME,password=PASSWORD,gid=1000,uid=1000,iocharset=utf8 0 0

J'utilise un compte qui a des droits minimums

Créer le point de montage

  1. mkdir /media/applic

Et monter le dossier

  1. mount /media/applic

A ce stade là, le serveur mail sait communiquer avec son voisin, pour accéder au partage réseau applic$, on en aura besoin pour déposer les résultats de laboratoire. (il savait déja le faire mais pour le partage intranet).

Installer l'appli apiuncrypt

créer les dossier nécessaires.
  1. mkdir /home/virtual/apicrypt

Le dossier home/virtual contient les "maildir" (traduction: les mails sous formes des fichiers des utilisateurs) Si c'est le dossier de "virtual" c'est parceque les utilisateurs ne sont pas (plus) des comptes unix, mais des enregistrements dans une base de données, et donc des utilisateurs virtuels. Je m'égare.... ça m'arrange de tout mettre là, car le script je vais le faire marcher par le compte système unix vmail. C'est lui qui a les droits sur les mails (hormis root) et ça m'arrange de tout lui regrouper dans son home.

je me place dans le dossier, je télécharge l'appli qui décrypte les mails, et je crée le dossier pour les clés de décriptage.

  1. cd /home/virtual/apicrypt
  2. wget http://www.apicrypt.org/page5/files/linux/apiuncrypt.tgz
  3. tar -xvf apiuncrypt.tgz
  4. mkdir Clefs

Déposer les clefs de décryptage (le master et la clé personnelle) de l'année en cours UNIQUEMENT dans le dossier Clefs (attention il est sensible à la casse le C est en majuscule).

rendre les droits à vmail

  1. chown -R vmail:vmail /home/virtual/

MAJ 21/06/2011 Pour un serveur à architecture 64 bits (testé sur une débian 6)

L'association apycript n'ayant pas mis à jour la librairie depuis 2006, forcément ça ne passe plus. Il va falloir installer la libstdc++-libc6.2-2.so.3 ... qui n'est trouvable qu'en i386.

  1. wget http://ubuntu.mirror.cambrium.nl/ubuntu//pool/universe/g/gcc-2.95/libstdc++2.10-glibc2.2_2.95.4-24_i386.deb
  2. dpkg -i --force-architecture libstdc++2.10-glibc2.2_2.95.4-24_i386.deb
  3. ln -s /usr/lib/libstdc++-libc6.2-2.so.3 /usr/lib/libstdc++libc6.1-1.so.2

Fin de la partie spécifique serveur 64 bits...

Le script qui lancera le décryptage des mails. et pousse les fichiers textes décryptés dans le répertoire où le logiciel de dossier de soins va les chercher.

Pour le moment c'est un script shell enregistré en tache cron, exécuté par le compte vmail. Je le remplacerai par des regles "mailfilter" ou procmailrc dès que je saurai le faire (plus propre).

je l'ai mis là: /home/virtual/apicrypt/Uncryptbal.sh et voici ma composition:

  1. ##!/bin/sh
  2. #by Gnieark http://blog-du-grouik.tinad.fr
  3. #version 0 fevrier 2010
  4. # Le contenu de ce code est distribué en licence Cecill V2,
  5. #qui dit grossomodo que c'est libre de droits, sauf la marque de paternité du code (pour ma gloire),
  6. #mais aussi que je ne suis pas responsable si ce code fait une connerie . Vous disposez de la source, donc pouvez le vérifier et le modifier,
  7. #je vous le met à disposition gratuitement. Il est de votre responsabilité de tester préalablement tous les cas de figures, avant sa mise en production.
  8. #la license est disponible là: http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt
  9. #
  10. #Liste les fichiers "mails d'un repertoire", décrypte le corps via la moulinette apycript et les envoie dans le dossier pour l'application de dossier de soins.
  11. #
  12. #variables chemins
  13. repertoireorigine="/home/virtual/DOSSIER DE L'ADRESSE MAIL DEDIEE AU LABO/new"
  14. repertoiredestination="/media/applic/soins/resultatslabo/Data/Reception/A classer/"
  15. cheminapiuncrypt="/home/virtual/apicrypt/apiuncrypt"
  16. chemincles="/home/virtual/apicrypt/"
  17. fichierlog="/home/virtual/apicrypt/log.txt"
  18. fichiertemp="/home/virtual/apicrypt/temp.txt"
  19. #variable d'erreur (déclenchera une alerte à la fin du script)
  20. erreur=0
  21.  
  22. #log:
  23. echo "$(date) Début du script décriptage de la bal pour les résultats laboratoire ">>$fichierlog
  24.  
  25.  
  26. #supprmmer le fichier temporaire s'il existe
  27. if [ -e "$fichiertemp" ];
  28. then
  29. rm $fichiertemp
  30. echo "$(date) Le fichier temp.txt existait, suppression">> $fichierlog
  31. else
  32. echo "$(date) Le fichier temp.txt n'existait pas (normal)">> $fichierlog
  33. fi
  34. #lister les fichiers dans le repertoire
  35. find $repertoireorigine -type f > $fichiertemp
  36.  
  37. while read line; do
  38.  
  39. $cheminapiuncrypt -s $line -k $chemincles
  40.  
  41. #vérifier si le fichier.txt a ete créé
  42. if [ -e "$line.txt" ];
  43. then
  44. echo "$(date) Le fichier $line.txt décrypté a été créé">> $fichierlog
  45. #on envoit le fichier dans son repertoire de destination
  46.  
  47. mv "$line.txt" "$repertoiredestination"
  48. fichier = basename $line.txt
  49.  
  50. #vérifier si le tranfert s'effectue
  51. if [ -e "$repertoiredestination$fichier" ];
  52. then
  53. #c'est ok
  54. rm $line
  55. echo "$(date) -OK-le fichier $line transfert ok">> $fichierlog
  56. else
  57.  
  58.  
  59. #probleme
  60. echo "$(date) -WARNING- le fichier $line.txt transfert échoué">> $fichierlog
  61. erreur=2
  62. fi
  63.  
  64. else
  65. echo "($date) -WARNING- le fichier $line n'a pas été décrypté"
  66. erreur=1
  67. fi
  68. done < $fichiertemp
  69.  
  70. if [ $erreur = 1 ];
  71. then
  72. echo "Erreur de type 1 sur l'interface laboratoire. Un des fichiers n'a pas pu être décrypté (Il est probable qu'il sagisse d'un spam ou d'un mail \"parasite\" Le message d'origine n'a pas été supprimé" > $fichiertemp
  73. mail -s "Erreur sur l'interface de laboratoire" "MAILS DES DESTINATAIRES DES ALERTES" < $fichiertemp
  74. fi
  75.  
  76. if [ $erreur = 2 ];
  77. then
  78. echo "Erreur de type 2 sur l'interface laboratoire. Le transfert d'un des fichiers décryptés n'a pas été effectué, vérifiez que $repertoiredestination est une ressource disponible" > $fichiertemp
  79. mail -s "Erreur sur l'interface de laboratoire" "MAILS DES DESTINATAIRES DES ALERTES" < $fichiertemp
  80. fi
  81.  
  82. echo "$(date) Fin du script décriptage de la bal pour les résultats laboratoire ">>$fichierlog

Il est un chouilla long, parcequ'il vérifie à plusieurs endroits si les étapes se sont bien déroulées et envoie un mail d'alerte en cas d'erreur. De plus les actions du script sont logguées.

Créer la crontab pour que le script soit exécuté automatiquement

  1. crontab -e

Aouter la ligne suivante:

  1. */5 * * * * su -c '/home/virtual/apicrypt/Uncryptbal.sh' vmail

Mise à jour des clés.

Il suffira de les déposer das le dossier prévu. et supprimer les anciennes (sinon ça marche pas)

Notes

[1] le serveur est sous debian lenny, mais pour les quelques essais sous ubuntu, j'ai eu des problèmes de dépendances ne se trouvant plus dans les paquets de la distribution

- page 1 de 2


Tous les billets de cette catégorie:

Propulsé par Dotclear