Qu'est-ce qu'un bon exemple de commandes de tuyauterie ensemble?

33

Si vous aidiez quelqu'un à apprendre le concept des pipes sur la ligne de commande, quel exemple utiliseriez-vous? L’exemple qui a été cité est le suivant:

cat whatever.txt | less

J'ai l'impression que ce n'est pas le meilleur exemple, à savoir parce qu'il n'y a qu'un pas. Qu'est-ce qu'un bon usage, mais fondamental |?

Idéalement, l'exemple que je vais présenter utilisera des programmes dont les sorties elles-mêmes peuvent être exécutées indépendamment, puis affichées ensemble.

Matthieu
la source
3
Votre exemple n’est vraiment pas très bon. Il s’agit essentiellement d’une candidature pour le prix «utilisation inutile du chat».
maxschlepzig
@maxschlepzig Non pas que vous vous trompiez, mais vous n'êtes pas très utile non plus; vous n'avez pas besoin catde cela car cela less whatever.txtfonctionne très bien.
Bora M. Alper

Réponses:

34

Je vais vous montrer un exemple un peu complexe, basé sur un scénario réel.

Problème

Disons que la commande a conkycessé de répondre sur mon bureau et que je veux la tuer manuellement. Je connais un peu Unix, donc je sais que ce que je dois faire, c'est exécuter la commande kill <PID>. Pour récupérer le PID, je peux utiliser psou topou tout autre outil ma distribution Unix m'a donné. Mais comment puis-je faire cela en une seule commande?

Répondre

$ ps aux | grep conky | grep -v grep | awk '{print $2}' | xargs kill

DISCLAIMER: Cette commande ne fonctionne que dans certains cas. Ne le copiez / collez pas dans votre terminal et ne commencez pas à l’utiliser, cela pourrait tuer des processus sans le savoir Apprenez plutôt comment le construire .

Comment ça marche

1- ps aux

Cette commande affichera la liste des processus en cours et des informations les concernant. L'information intéressante est qu'il va sortir le PID de chaque processus dans sa 2e colonne. Voici un extrait de la sortie de la commande sur ma boîte:

$ ps aux
 rahmu     1925  0.0  0.1 129328  6112 ?        S    11:55   0:06 tint2
 rahmu     1931  0.0  0.3 154992 12108 ?        S    11:55   0:00 volumeicon
 rahmu     1933  0.1  0.2 134716  9460 ?        S    11:55   0:24 parcellite
 rahmu     1940  0.0  0.0  30416  3008 ?        S    11:55   0:10 xcompmgr -cC -t-5 -l-5 -r4.2 -o.55 -D6
 rahmu     1941  0.0  0.2 160336  8928 ?        Ss   11:55   0:00 xfce4-power-manager
 rahmu     1943  0.0  0.0  32792  1964 ?        S    11:55   0:00 /usr/lib/xfconf/xfconfd
 rahmu     1945  0.0  0.0  17584  1292 ?        S    11:55   0:00 /usr/lib/gamin/gam_server
 rahmu     1946  0.0  0.5 203016 19552 ?        S    11:55   0:00 python /usr/bin/system-config-printer-applet
 rahmu     1947  0.0  0.3 171840 12872 ?        S    11:55   0:00 nm-applet --sm-disable
 rahmu     1948  0.2  0.0 276000  3564 ?        Sl   11:55   0:38 conky -q

2- grep conky

Je ne suis intéressé que par un processus, je greprecherche donc l'entrée correspondant à mon programme conky.

$ ps aux | grep conky
 rahmu     1948  0.2  0.0 276000  3564 ?        Sl   11:55   0:39 conky -q
 rahmu     3233  0.0  0.0   7592   840 pts/1    S+   16:55   0:00 grep conky

3- grep -v grep

Comme vous pouvez le constater à l'étape 2, la commande psaffiche le grep conkyprocessus dans sa liste (c'est un processus en cours d'exécution). Pour le filtrer, je peux courir grep -v grep. L'option -vindique de grepfaire correspondre toutes les lignes à l' exclusion de celles contenant le motif.

$ ps aux | grep conky | grep -v grep
 rahmu     1948  0.2  0.0 276000  3564 ?        Sl   11:55   0:39 conky -q

NB: J'aimerais savoir comment faire les étapes 2 et 3 en un seul grepappel.

4- awk '{print $2}'

Maintenant que j'ai isolé mon processus cible. Je veux récupérer son PID. En d'autres termes, je veux récupérer le deuxième mot de la sortie. Heureusement pour moi, la plupart (tous?) Les ordinateurs modernes fourniront une version de awk, un langage de script qui fait des merveilles avec des données tabulaires. Notre tâche devient aussi facile que print $2.

$ ps aux | grep conky | grep -v grep | awk '{print $2}'
 1948

5- xargs kill

J'ai le PID. Tout ce dont j'ai besoin est de le transmettre kill. Pour ce faire, je vais utiliser xargs.

xargs killlit à partir de l'entrée (dans notre cas à partir du tube), forme une commande composée de kill <items>( <items>est ce qu'il lit à partir de l'entrée), puis exécute la commande créée. Dans notre cas, il va exécuter kill 1948. Mission accomplie.

Mots finaux

Notez que, selon la version de votre système d'exploitation Unix utilisée, certains programmes peuvent se comporter légèrement différemment (par exemple, psle PID peut être généré dans la colonne $ 3). Si quelque chose semble faux ou différent, lisez la documentation de votre fournisseur (ou mieux, les manpages). Faites également attention car de longs tuyaux peuvent être dangereux. Ne faites pas de suppositions, en particulier lorsque vous utilisez des commandes telles que killou rm. Par exemple, s'il y avait un autre utilisateur nommé 'conky' (ou 'Aconkyous'), ma commande pourrait également tuer tous ses processus en cours d'exécution!

Ce que je dis, c'est de faire attention, surtout pour les longues pipes. Il est toujours préférable de le construire de manière interactive comme nous l'avons fait ici, plutôt que de formuler des hypothèses et de vous sentir désolé plus tard.

Rahmu
la source
NB: J'aimerais bien savoir comment faire les étapes 2 et 3 en un seul appel grep. -> grep "conky -q" :)
Wolfy le
3
En fait, c’est un mauvais exemple, comme vous pourriez simplement le fairekill $(pgrep conky)
Patrick
5
Je sais que c'est en retard, mais vous pouvez simplifier encore plus loinpkill conky
strugee
2
"" "NB: j'aimerais connaître le moyen d'effectuer les étapes 2 et 3 en un seul appel grep." "" Au lieu de "aux", utilisez "-o pid, comm" - cette option est également plus portable car elle est POSIX -compliant. De cette façon, le processus grep s'affichera simplement en tant que "grep" au lieu de "grep conky", de sorte qu'il ne se correspondra pas.
Aléatoire832
2
NB: J'aimerais savoir comment faire les étapes 2 et 3 en un seul grepappel. grep [c]onkyest ce que vous cherchez.
AlexT
15

Mon préféré est celui-ci:

youtube-dl $1 -q -o - | ffmpeg -i - $2

télécharge une vidéo à partir de l’URL youtube donnée passée $1et l’affiche sous forme de fichier donné par $2. Notez que le fichier est sorti en mode silencieux -qvers STDOUT -o -, transmis à ffmpeg et utilisé comme entrée par celui-ci -i -.

Cela pourrait être un exemple pratique, en particulier pour les débutants sous Linux, des raisons pour lesquelles la ligne de commande peut être utile et simplifier les choses plutôt que d'utiliser des outils graphiques. Je ne sais pas combien de temps il faudrait pour télécharger une vidéo à partir de youtube et convertir son son en mp3. La ligne ci-dessus peut le faire en quelques secondes.

Baarn
la source
3
YouTube-dl a une option pour enregistrer uniquement l'audio. Ma commande habituelle est celui -ci où les URL sont disponibles dans le stdin: youtube-dl --extract-audio --audio-format mp3 -a -. Encore un bon exemple, mais il existe des moyens plus simples de le faire. (Il appelle ffmpeg en interne.)
Brigand le
3
@FakeRainBrigand: Haha, bon à savoir! Mais j'ai une alternative qui ne devrait pas être intégrée: youtube-dl $1 -q -o - | mplayer -joue directement la vidéo dans mplayer. J'utilise cette commande de mon ordinateur portable pour dire à mon serveur (qui est connecté au téléviseur) de lire des vidéos. Je dois ajouter -display :0.0 -geometry 400x300+1200+200pour que la fenêtre mplayer apparaisse sur le bon écran.
Baarn
9

L’utilisation générale (lire: la façon dont je l’utilise la plupart du temps) correspond au moment où, pour une raison quelconque, je dois exécuter des données à travers plusieurs outils pour effectuer différentes tâches de traitement.

Je dirais donc que l’ utilisation de tuyaux est comme une colle pour assembler plusieurs blocs de construction (les différents outils UNIX). Comme Ulrich a dit, sortet uniqest une strophe commune.

Selon le public cible, si vous souhaitez mettre en évidence cette utilisation des pipes, vous pouvez par exemple commencer par: "hé, ce programme contient des liens vers plusieurs PDF intéressants avec des papiers et des notes de cours, mais certaines d'entre elles sont répétées. en quelque sorte automatiser cela? "

Ensuite, vous pouvez montrer comment lynx --dump --listonlyobtient la liste des liens, comment grepfiltrer les liens se terminant par .pdf,colrm oused supprimer les numéros lynxlaissés sur chaque URL, comment sortet comment uniqsupprimer les doublons, et enfin, comment wget -i -récupérer les fichiers (en utilisant --waitêtre doux sur le serveur, bien sûr).

Je crains que ce soit un exemple complexe. D'autre part, il peut être utile de montrer la puissance des tuyaux lorsque vous le faites simplement et que le shell le fait fonctionner en même temps.

njsg
la source
2
Vous pouvez utiliser sort -udans GNU coreutils aussi.
Teresa e Junior
2

Je ne sais pas exactement à propos de bien, mais passe à travers grep doit être l’une des utilisations les plus courantes, éventuellement suivie de wc -l. (Oui, grepl' -cinterrupteur peu connu .)

Une autre strophe courante est | sort | uniq, ne serait-ce que parce uniqque son entrée doit être triée.

Ulrich Schwarz
la source
La plupart des gens préfèrent ... | sort -usi disponible!
2

Non pas que vous en ayez besoin pour cet exemple, mais:

$ ps aux | grep -v grep | grep conky

... inverser l'ordre des greps préserve la colorisation, mais BEAUCOUP moins efficace. vraisemblablement sur de grandes listes, la couleur n'aurait pas d'importance.

De plus, cette page Web suggère:

https://stackoverflow.com/questions/9375711/more-elegant-ps-aux-grep-v-grep

> Johnsyweb répondu 21 février 12 à 10:31
> Le truc habituel est le suivant:
> ps aux | grep '[t] erminal'
> Ceci correspondra aux lignes contenant le terminal, ce que grep '[t] erminal' ne fait pas!
> Cela fonctionne également sur de nombreuses versions d'Unix.

... mais cela ne fonctionnera pas si vous recherchez une seule lettre (comme le processus 'X').

anonymuse
la source
2

J'ai enfin l'occasion de partager ce gâchis d'un film que j'ai fabriqué il y a environ un an et demi ...

while read in; do host "$in"; done < sites.txt | grep -iv "GOOGLE" | grep -E '1\.2\.3\.4|5\.6\.7\.8' | sed -e 's/has\ address\ 216.70.91.72//' | sed -e 's/has\ address\ 94.23.33.92//' | while read sites; do curl -sL -w "%{http_code} %{url_effective}\\n" "$sites" -o /dev/null; done | grep -ivE '4.*|5.*' | sed -e 's/200//' | sed -e 's/HTTP/http/'

Il...

  1. Lit sites.txt
  2. Lance "hôte" sur chacun (avec le recul, dig + short aurait rendu cela beaucoup plus facile)
  3. Supprime les lignes contenant "GOOGLE" - ce sont les enregistrements mx
  4. Obtient les lignes qui ont l'un des deux IP
  5. Obtient le code de statut http de chaque site de la liste.
  6. Supprime les sites qui renvoient 4xx ou 5xx
  7. Enlève le "200" des sites qui ont renvoyé cette
  8. Remplace "HTTP" par "http" - purement esthétique, sans véritable raison.

Cela aurait pu être beaucoup mieux fait avec un seul script Python, je parie.

tanneur
la source
Euh ... je ne suis pas sûr que ce soit l'exemple le plus propre et le plus simple pour expliquer la tuyauterie à un débutant;)
Erathiel
2
Ma question est, quel est son but?
ADTC
J'avais un fichier plein de domaines, et j'avais besoin de voir s'ils se trouvaient sur l'un de mes deux serveurs (que j'ai "hérité", malheureusement). Cela lit le fichier, "hôte" et nettoie cette sortie, puis demande simplement si elle renvoie une erreur 4xx ou 5xx. Si c'était le cas, alors le domaine serait ignoré; sinon, il les sort et je les mets dans un autre fichier.
tanneur
1

C'est la première chose qui m'est venue à l'esprit ...

mysqldumpest une application console qui envoie des données, un schéma et éventuellement des procédures et des fonctions à stdout. Habituellement, il est redirigé vers un fichier pour la sauvegarde.

mysqldump <options> > mydb.dump

Cela vous donnerait un script SQL non compressé. Pour économiser de l'espace, vous pouvez le compresser avec bzip2.

bzip2 mydb.dump

Alternativement, vous pouvez faire les deux en une étape:

mysqldump <options> | bzip2 > mydb.dump.bz2

Dans cet exemple ci-dessus, le stdout de mysqldumpest envoyé à bzip2 qui redirige ensuite sa sortie vers un fichier.

Sean C.
la source
1
Ajouter l'opération trop inverse: bzcat mydb.dump.bz2 | mysql <options>.
Manatwork
1

Voici un exemple que j'utilise dans mon travail pour plusieurs canaux en une seule commande. Cela utilise gawk pour rechercher le journal de requête général de MySQL ($ OFILE) et trouver toutes les connexions refusées. Il trie ensuite cette liste par nom, transmet cette liste à uniq qui compte les occurrences, puis trie une dernière fois la liste comptée ...

gawk '{ for (x=1;x<=NF;x++) if ( $x~"Access" && $(x+4)~".*@.*") print $(x+4)}' $OFILE | sort | uniq -c | sort -n
Rob Berkes
la source
1

Les tuyaux fonctionnent mieux avec des filtres et des traducteurs

find /usr/bin/ |                #produce 
sed 's:.*/::'  |                #translate: strip directory part
grep -i '^z'   |                #filter   : select items starting with z
xargs -d '\n' aFinalConsumer    #consume  

De cette façon, les données peuvent circuler d'un programme à un autre en mémoire tampon et à aucun moment toutes les données ne doivent être en mémoire en même temps.

PSkocik
la source
0

cat filename | less est une utilisation terrible de la tuyauterie puisque vous pouvez simplement faire less filename

Voici un exemple de pépins que j'utilise tous les jours (mais cela peut aussi être un mauvais exemple): ls -la | more -c

Les réponses de Scott Hoffman et NJSG en sont de meilleurs exemples.

DwB
la source
0

exécutez celui-ci dans le répertoire de votre choix pour analyser la taille du dossier (puis faites défiler vers le bas avec la touche FIN):

du -m| sort -n| less

Sortiert nach Ordnergrösse

xubunuser
la source
0

Voici un exemple que j'ai utilisé pour définir la variable DISPLAY alors que xauth n'était pas une option ...

export DISPLAY=\`who am i |awk '{print $NF}' | sed 's/[()]//g'`":0.0"

La première commande récupère les données nécessaires, c'est-à-dire le nom d'hôte ou l'adresse IP. La deuxième commande récupère uniquement ces données (dernier champ). Enfin, la dernière commande supprime les parenthèses des données.

Scott Hoffman
la source
0

La tuyauterie de commande que vous pouvez utiliser n’importe où, selon vous, la sortie de la première commande peut être transmise en entrée.

Exemples.

  1. Avec les fichiers texte, vous pouvez transmettre le fichier texte à grep pour rechercher des lignes de texte particulières. Ensuite, vous pouvez transmettre la sortie à sed ou awk pour modifier ou imprimer certaines parties de la ligne.

exemple de chat txt | grep {une_ligne} | awk {une_commande}

  1. En travaillant avec process, vous pouvez utiliser la tuyauterie pour envoyer des commandes afin de tuer le processus.

C'est simplement le concept que si vous sentez que la sortie de commande que vous avez exécutée peut être entrée d'une autre commande, vous pouvez la diriger.

Piyush Jain
la source