Skip to content

Linux Attitude

Le libre est un état d'esprit

Archive

Archive for June, 2007

Niveau :      
Résumé : exec 3>&1 ; { 2>&1 1>&3; } 3>&1 1>&2 ; exec 3>&-

Aujourd'hui quelques astuces sur les pipes et les redirections en bash. Le but final de cet article étant le filtrage de stderr (sortie d'erreur) dans un pipe comme vous le feriez naturellement avec stdout (sorti standard). Vous verrez que ce n'est pas si évident.

Les fondations

Tout d'abord le pipe simple '|' :

$ echo toto | grep -v toto
>

Passons par stderr :

$ echo toto 1>&2 | grep -v toto
> toto

1>&2 permet de rediriger stdout sur sterr,

Pour ceux qui prennent le train en marche : 0=stdin (le clavier), 1=stdout (l'ecran), 2=stderr (l'ecran aussi). Le stdin du côté droit du pipe '|' prend toujours sa source du stdout du côté gauche. Le stderr lui, traverse toute la commande d'un coup pour atterrir sur le stderr final.

Notez que le 1 est optionnel à gauche de >.

Première brique

Tout d'abord apprenons à ouvrir un nouveau file descriptor pour le plaisir. Celui-ci devra nécessairement pointer sur quelque chose. Donc nous le ferons simplement sortir sur stdout :

$ exec 3>&1
$ echo toto >&3
> toto

Pour fermer ce même file descriptor :

$ exec 3>&-
$ echo toto >&3
> bash: 3: Mauvais descripteur de fichier

continue reading...

Niveau :      
Résumé : hts ; htc ; ssh-https-tunnel

Comme beaucoup de monde, vous êtes coincés au boulot et vous aimeriez bien accéder en ssh chez vous. Heureusement votre patron pense à votre sécurité et vous empêche d'accéder au dangereux protocole ssh.

Mais il sait que le web est bon et vous autorise à le parcourir, mais seulement sous la garde d'un proxy. C'est là que votre foreuse entre en jeu. Tout d'abord un bon principe sur internet : un protocole reste ce qu'il est, c'est-à-dire une couche sous une autre et sur une autre. Ce qui veut dire qu'avec un peu d'effort il est possible de faire passer n'importe quel protocole sur n'importe quel autre.

Httptunnel

Commençons par le plus simple, le paquet httptunnel. Il contient 2 outils, un client et un serveur qui transformeront toute connexion TCP en protocole HTTP. On peut ainsi traverser les firewalls et la plupart des proxy et y faire passer notre connexion ssh typique.

Sur le serveur, il va falloir écouter sur un port "acceptable" par votre proxy, par exemple le 8080

$ hts -F localhost:22 8080

Côté client

$ htc -F 1022 -P proxy.local.net:3128 serveur.machine.net:8080

Et voila, le port 1022 sur la machine locale est automatiquement redirigé vers le port 22 de serveur.machine.net. Testons :

$ ssh -p1022 localhost

ssh-https-tunnel

Si votre proxy refuse les connexions http mais accepte les connexions https, le script suivant vous permettra de vous connecter à travers un tel proxy directement sur un serveur ssh ouvert sur le port 443 (vous ferez écouter votre serveur ssh directement sur ce port).

$ HTTP_PROXY=http://proxy.local.net:8080 ./ssh-https-tunnel ma.machine.net 443

Et voila, vous êtes connectés.

De nombreux autres systèmes de tunnels sont disponibles en fonction de vos contraintes.

PS : C'est à vous de savoir si vous avez le droit de faire ceci au boulot ou non. PS2: S'il y a un IDS sur votre réseau, lisez les commentaires

Niveau :      
Résumé : comm -1 -2 ; diff -y

Supposons que vous ayez 2 listes. Par exemple la liste des courses et la liste des produits achetés. Il vous est possible de récupérer la liste des éléments communs grâce à la méthode suivante :

$ sort liste1 > liste1.tmp
$ sort liste2 > liste2.tmp
$ comm -1 -2 liste1.tmp liste2.tmp
  • on fait un sort car comm ne fonctionne que sur des fichiers dont les lignes sont ordonnées de la même façon
  • -1 et -2 indiquent de ne pas garder les lignes uniques au fichier 1 ou au fichier 2 (donc les lignes communes)

Notez que si vous aviez plusieurs fois les mêmes lignes dans vos fichiers, il se peut que vous vouliez ne comparer que des lignes différentes (ne pas compter le sel comme non acheté s'il est écrit 2 fois dans la liste des courses par exemple). Dans ce cas vous utiliserez les commandes suivantes :

$ sort liste1 | uniq > liste1.tmp
# ou
$ sort -u liste2 > liste2.tmp



Toujours en utilisant comm, vous pouvez obtenir les éléments présents dans la liste 1 et pas dans la liste 2 (et pas communs). Il vous faut alors utiliser les options "-2 -3".

Sans options comm affiche les données sur 3 colonnes :

$ comm liste1.tmp liste2.tmp

Ceci permet de comparer les fichiers en affichant sur la première colonne les données uniques au fichier 1, sur la 2e les données uniques au fichier 2 et sur la 3e les données communes.

Notez que pour une comparaison visuelle des 2 fichiers (mais plus difficilement scriptable cette fois), la commande diff est plus adaptée :

$ diff -y liste1.tmp liste2.tmp

On a alors les 2 fichiers affichés sur 2 colonnes et un petit caractère > ou < indique si la ligne n'apparaît que sur un des 2 fichiers.

Niveau :      
Résumé : lspci ; lshw : lsusb ; dmidecode

Pour savoir quel matériel constitue votre machine vous avez plusieurs commandes à votre disposition. La première, la plus courante est lspci :

$ lspci

Elle vous donne un aperçu simple et rapide des périphériques tournant sur le bus pci, cela inclue les contrôleurs usb, les ports isa ...

Une autre commande peut vous donner des informations bien plus détaillées sur ces périphériques, mais aussi ceux de beaucoup d'autres (par exemple la liste des barrettes mémoire) :

$ lshw

Option -short pour avoir une simple liste avec moins de détails (notez que vous aurez plus d'informations en étant root qu'utilisateur normal) :

$ lshw -short

Notez que dmidecode peut vous afficher le même genre d'information avec encore plus de détails , mais cette fois en lisant les informations fournies par le bios (il faut être root) :

$ dmidecode -q

L'intérêt de dmidecode est qu'il permet de lire des informations détaillées sur un type de périphérique précis, par contre il n'en connaît pas autant que lshw :

$ dmidecode -t bios

Si vous cherchez uniquement la liste des périphériques usb :

$ lsusb -t

Notez l'option -t qui vous permet de distinguer du premier coup d'oeil les point d'accès, les hubs et les périphériques.

Dans un prochain article nous verrons les informations que peuvent nous donner /proc et /sys.

Niveau :      
Résumé : ccze -A

Coloration

Un bon admin doit lire ses logs régulièrement. En général il le fait parce qu'un système de surveillance lui a remonté un problème. Les logs sont souvent très denses. Mais il existe un moyen pour les rendre plus lisibles. Il s'agit de colorer le texte.

Pour cela il existe une commande qui s'appelle ccze (du paquet du même nom). Pour colorer les logs d'un fichier, c'est facile :

$ ccze < /var/log/syslog

L'inconvénient est que ccze colore tout le fichier d'un coup et ne vous laisse pas le temps de le lire. Nous allons donc le combiner avec une autre commande : less. Le seul problème est qu'un simple ccze | less nous rend les choses illisibles. La bonne méthode est la suivante :

$ ccze -A < /var/log/syslog | less -R
  • ccze -A : forcer l'utilisation des codes ANSI pour la coloration (pour traverser les pipe proprement)
  • less -R : empêcher l'interprétation des codes ANSI par less lui-même

Ceci concernait la lecture d'un fichier de log sur lequel on cherche des informations plus ou moins précises. Mais lorsque vous voulez juste surveiller un fichier de logs en continu, utilisez plutôt la commande suivante :

$ tail -f /var/log/syslog | ccze -A

Racourcis

Ainsi pour garder de bons réflexes, faites-vous les commandes suivantes à enregistrer dans votre .bashrc

$ lesslog() { ccze -A < $1 | less -R; }
$ logtail() { tail -f $1 | ccze -A; }

D'où des commandes accessibles par la suite :

$ lesslog /var/log/syslog
$ logtail /var/lor/syslog

Et notez que ccze ne sait pas colorer que les fichiers de syslog, mais aussi de nombreux types de fichiers de logs. Pour en connaître la liste :

$ ccze -l

Niveau :      
Résumé : kill -9 $$

Article court mais efficace.

Supposons que vous soyez en train de triturer une machine et que vous ne vouliez pas qu'on sache ce que vous faites. Vous voudriez évidemment ne pas laisser de traces. Malheureusement, tout ce que vous faites est enregistré dans le fichier de log du shell. Ce fichier étant enregistré uniquement à la fin de votre session, il est possible d'empêcher cette écriture en tuant le shell plutôt qu'en quittant normalement. Tout simplement :

$ kill -9 $$

Mais bon, n'oubliez pas que votre connexion restera quand même visible dans le lastlog qui liste les dates et heures de connexion ;

$ last

Niveau :      
Résumé : scp machine1:~/file machine2:~/

FXP

Le FXP est un détournement du protocole FTP. Le FTP utilisant une connexion différente pour les données et pour les commandes, il est possible d'ouvrir une connexion de commande sur 2 machines et de leur demander d'ouvrir la connexion de données entre elles deux, rien ne passe par vous. Explication plus détaillée.

En pratique, la plupart des clients ftp supportent ce système nativement (même en ligne de commande).

SCP

Maintenant supposons que vous n'ayez que ssh à disposition. Hé bien il est possible de faire le même genre de chose :

$ scp user1@machine1:/my/file/1 user2@machine2:/your/path

Le processus est alors le suivant :

  • scp vous connecte sur machine 1 (avec mot de passe si besoin)
  • puis depuis machine1, il tente de se connecter à user2@machine2 pour faire la copie (sans interaction cette fois).

Ceci a 2 inconvénients :

  • si le flux ssh n'est pas ouvert de machine1 vers machine2 vous êtes coincés
  • il faut que vous puissiez vous connecter de machine1 à machine2 sans mot de passe (avec une clé et un forward d'agent)

Si le flux est ouvert de machine2 vers machine1 (dans l'autre sens) ou si vous n'avez pas de clé ssh, vous pouvez aussi utiliser la commande suivante :

$ ssh user2@machine2 "scp user1@machine1:/my/file/1 /your/path"

Et si aucun flux n'est ouvert entre machine1 et machine2 il vous reste une dernière solution : passer par votre machine de commande. Pour ne pas avoir à stocker le fichier sur votre machine (transit uniquement) utilisez la commande suivante :

$ ssh user1@machine1 "cat /my/file/1" | ssh machine2 "cat > /your/path/1"

PS : Dans vos commandes scp, il est possible d'écrire "machine:" comme équivalent de "machine:~/"

PS2 : Dans vos commandes, si le nom d'un fichier local contient un ":", il vous faut donner un chemin contenant un / pour ne pas confondre avec un nom de machine. Ex:

$ scp machine:~/toto ./mon:repertoire/