Heim  >  Artikel  >  System-Tutorial  >  Lernen Sie vom Anfänger bis zum Experten die Linux-Umleitungs- und Pipeline-Tools kennen, um Ihren Arbeitsablauf zu beschleunigen!

Lernen Sie vom Anfänger bis zum Experten die Linux-Umleitungs- und Pipeline-Tools kennen, um Ihren Arbeitsablauf zu beschleunigen!

PHPz
PHPznach vorne
2024-02-09 23:36:381200Durchsuche

Verbesserung der Arbeitseffizienz, Betriebssystemoptimierung, Automatisierung usw. sind die Ziele, die jeder IT-Praktiker verfolgt. Im Linux-Betriebssystem gehört die geschickte Verwendung von Umleitungs- und Pipeline-Befehlszeilentools zu den Fähigkeiten, die beherrscht werden müssen. In diesem Artikel werden die Verwendung und die Prinzipien von Umleitungs- und Pipeline-Tools anhand von Beispielen ausführlich erläutert.

Das Linux-System gefällt mir sehr gut, insbesondere einige der Designs von Linux sind sehr schön. Beispielsweise können einige komplexe Probleme in mehrere kleine Probleme zerlegt und durch den Pipe-Charakter und die Umleitung flexibel mit vorgefertigten Tools gelöst werden Mechanismus. Es ist sehr effizient, ein Shell-Skript zu schreiben.

Lernen Sie vom Anfänger bis zum Experten die Linux-Umleitungs- und Pipeline-Tools kennen, um Ihren Arbeitsablauf zu beschleunigen!

In diesem Artikel werden einige der Fallstricke erläutert, auf die ich bei der Verwendung von Umleitungs- und Pipe-Zeichen in der Praxis gestoßen bin. Durch das Verständnis einiger zugrunde liegender Prinzipien kann die Effizienz beim Schreiben von Skripten erheblich verbessert werden.

Die Fallstricke von

> und >> Zeichen umleiten

Lassen Sie uns zunächst über die erste Frage sprechen: Was passiert, wenn Sie den folgenden Befehl ausführen?

$ cat file.txt > file.txt

Das Lesen und Schreiben in dieselbe Datei fühlt sich an, als würde nichts passieren, oder?

Tatsächlich besteht das Ergebnis der Ausführung des obigen Befehls darin, dass der Inhalt der Datei file.txt gelöscht wird.

PS: Einige Linux-Distributionen melden Fehler möglicherweise direkt. Sie können catfile.txt ausführen, um diese Erkennung zu umgehen.

Wie im vorherigen Artikel über Linux-Prozesse und Dateideskriptoren erwähnt, muss sich das Programm selbst nicht darum kümmern, wo seine Standard-Eingabe-/Ausgabepunkte liegen. Es ist die Shell, die den Speicherort der Standard-Eingabe/Ausgabe des Programms durch Pipe-Zeichen und ändert Umleitungssymbole.

Wenn Sie also den Befehl cat file.txt > file.txt ausführen, öffnet die Shell zuerst file.txt. Da das Umleitungssymbol > ist, wird der Inhalt der Datei gelöscht und dann legt die Shell die Standardausgabe fest den cat-Befehl in die Datei .txt kopieren, dann beginnt die Ausführung des cat-Befehls.

Das heißt, der folgende Prozess:

1. Shell öffnet file.txt und löscht seinen Inhalt.
2. Shell verweist die Standardausgabe des Befehls cat auf die Datei file.txt.
3. Die Shell führt den Befehl cat aus und liest eine leere Datei.
4. Der Befehl cat schreibt eine leere Zeichenfolge in die Standardausgabe (Datei file.txt).

Das Endergebnis ist also, dass file.txt zu einer leeren Datei wird.

Wir wissen, dass > die Zieldatei löscht und >> den Inhalt an das Ende der Zieldatei anfügt. Was passiert also, wenn das Umleitungssymbol > in >> geändert wird?

$ echo hello world > file.txt # 文件中只有一行内容 
$ cat file.txt >> file.txt # 这个命令会死循环 

Eine Zeile Inhalt wird zunächst in file.txt geschrieben. Nach der Ausführung von cat file.txt >> file.txt sollte das erwartete Ergebnis zwei Zeilen Inhalt sein.

Aber leider ist das Laufergebnis nicht wie erwartet. Stattdessen wird „Hallo Welt“ in einer Endlosschleife in die Datei geschrieben. Die Datei wird bald sehr groß und der Befehl kann nur mit Strg+C gestoppt werden.

Das ist interessant, warum gibt es tatsächlich eine Endlosschleife? Nach einer kleinen Analyse können Sie sich den Grund vorstellen:

Erinnern Sie sich zunächst an das Verhalten des cat-Befehls. Wenn Sie nur den cat-Befehl ausführen, wird die Eingabe von der Befehlszeile gelesen Der Befehl führt den Befehl einzeln aus. Die Zeile liest die Daten und gibt sie dann aus.

Dann ist der Ausführungsprozess des Befehls cat file.txt >> file.txt wie folgt:

1. Öffnen Sie file.txt und bereiten Sie das Anhängen von Inhalten an das Ende der Datei vor.
2. Verweisen Sie die Standardausgabe des Befehls cat auf die Datei file.txt.
3. Der Befehl cat liest eine Inhaltszeile in file.txt und schreibt sie in die Standardausgabe (hängt sie an die Datei file.txt an).
4. Da gerade eine Datenzeile geschrieben wurde, stellt der Befehl cat fest, dass in file.txt noch lesbarer Inhalt vorhanden ist, und wiederholt Schritt 3.

Der obige Vorgang ähnelt dem Durchlaufen der Liste und dem gleichzeitigen Anhängen von Elementen an die Liste. Er wird nie vollständig durchlaufen, was zu einer Endlosschleife unserer Befehle führt.

> Das Umleitungszeichen und das Pipe-Zeichen | wirken zusammen

Wir müssen oft die ersten XX Zeilen der Datei abfangen und den Rest löschen.

Unter Linux kann der Befehl head die Funktion des Abfangens der ersten paar Zeilen einer Datei abschließen:

$ cat file.txt # file.txt 中有五行内容 
1 
2 
3 
4 
5 
$ head -n 2 file.txt # head 命令读取前两行 
1 
2 
$ cat file.txt | head -n 2 # head 也可以读取标准输入 
1 
2 

Wenn wir die ersten beiden Zeilen der Datei behalten und den Rest löschen möchten, können wir den folgenden Befehl verwenden:

$ head -n 2 file.txt > file.txt 

Aber dadurch wird der oben erwähnte Fehler gemacht. Am Ende wird file.txt gelöscht, was unsere Anforderungen nicht erfüllen kann.

Wenn wir den Befehl dann so schreiben, können wir Fallstricke vermeiden:

$ cat file.txt | head -n 2 > file.txt 

Die Schlussfolgerung ist, dass es nicht funktioniert, der Dateiinhalt wird trotzdem gelöscht.

Was? Gibt es ein Leck in der Pipeline und alle Daten gehen verloren?

Im vorherigen Artikel über Linux-Prozesse und Dateideskriptoren habe ich auch das Implementierungsprinzip des Pipe-Zeichens erwähnt. Im Wesentlichen verbindet es die Standardeingabe und -ausgabe zweier Befehle, sodass die Standardausgabe des vorherigen Befehls als Standardeingabe dient des nächsten Befehls.

Wenn Sie jedoch glauben, dass das Schreiben solcher Befehle die erwarteten Ergebnisse erzielen kann, liegt dies möglicherweise daran, dass die durch das Pipe-Zeichen verbundenen Befehle seriell ausgeführt werden. Dies ist tatsächlich ein häufiger Fehler Zeichen werden parallel ausgeführt.

Sie denken vielleicht, dass die Shell zuerst den Befehl cat file.txt ausführt, den gesamten Inhalt in file.txt normal liest und diesen Inhalt dann über eine Pipe an den Befehl head -n 2 > file.txt weiterleitet.

Obwohl der Inhalt in file.txt zu diesem Zeitpunkt gelöscht wird, liest head keine Daten aus der Datei, sondern Daten aus der Pipe, sodass es möglich sein sollte, zwei Datenzeilen korrekt in file.txt zu schreiben.

但实际上,上述理解是错误的,shell 会并行执行管道符连接的命令,比如说执行如下命令:

$ sleep 5 | sleep 5 

shell 会同时启动两个sleep进程,所以执行结果是睡眠 5 秒,而不是 10 秒。

这是有点违背直觉的,比如这种常见的命令:

$ cat filename | grep 'pattern' 

直觉好像是先执行cat命令一次性读取了filename中所有的内容,然后传递给grep命令进行搜索。

但实际上是cat和grep命令是同时执行的,之所以能得到预期的结果,是因为grep ‘pattern’会阻塞等待标准输入,而cat通过 Linux 管道向grep的标准输入写入数据。

执行下面这个命令能直观感受到cat和grep是在同时执行的,grep在实时处理我们用键盘输入的数据:

$ cat | grep 'pattern' 

说了这么多,再回顾一开始的问题:

$ cat file.txt | head -n 2 > file.txt 

cat命令和head会并行执行,谁先谁后不确定,执行结果也就不确定。

如果head命令先于cat执行,那么file.txt就会被先清空,cat也就读取不到任何内容;反之,如果cat先把文件的内容读取出来,那么可以得到预期的结果。

不过,通过我的实验(将这种并发情况重复 1w 次)发现,file.txt被清空这种错误情况出现的概率远大于预期结果出现的概率,这个暂时还不清楚是为什么,应该和 Linux 内核实现进程和管道的逻辑有关。

解决方案

说了这么多管道符和重定向符的特点,如何才能避免这个文件被清空的坑呢?

最靠谱的办法就是不要同时对同一个文件进行读写,而是通过临时文件的方式做一个中转。

比如说只保留file.txt文件中的头两行,可以这样写代码:

# 先把数据写入临时文件,然后覆盖原始文件

$ cat file.txt | head -n 2 > temp.txt && mv temp.txt file.txt

这是最简单,最可靠,万无一失的方法。

你如果嫌这段命令太长,也可以通过apt/brew/yum等包管理工具安装moreutils包,就会多出一个sponge命令,像这样使用:

# 先把数据传给 sponge,然后由 sponge 写入原始文件 
$ cat file.txt | head -n 2 | sponge file.txt 

sponge这个单词的意思是海绵,挺形象的,它会先把输入的数据「吸收」起来,最后再写入file.txt,核心思路和我们使用临时文件时类似的,这个「海绵」就好比一个临时文件,就可以避免同时打开同一个文件进行读写的问题。

在Linux操作系统中,重定向和管道是非常有用的命令行工具,可以让我们更好地掌握系统的运行状态和信息。掌握相关技能能够帮助我们更好地进行系统优化和自动化工作,从而更好地提高工作效率。相信通过本文的介绍,读者对重定向和管道的原理和使用方法都有了更为深入的了解。

Das obige ist der detaillierte Inhalt vonLernen Sie vom Anfänger bis zum Experten die Linux-Umleitungs- und Pipeline-Tools kennen, um Ihren Arbeitsablauf zu beschleunigen!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:lxlinux.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen