Mehrfaches Lesen aus einer TXT-Datei in der Bash (Parallelverarbeitung)

1526
user7423959

Hier ist ein einfaches Bash-Skript für den HTTP-Statuscode

while read url do urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) echo "$url $urlstatus" >> urlstatus.txt done < $1 

Ich lese die URL aus einer Textdatei, verarbeitet jedoch nur eine zu einem Zeitpunkt und nimmt zu viel Zeit in Anspruch. GNU parallel und xargs verarbeiten auch jeweils eine Zeile (getestet).

Wie kann eine gleichzeitige URL für die Verarbeitung verarbeitet werden, um das Timing zu verbessern? Mit anderen Worten: Threading von URL-Dateien anstelle von Bash-Befehlen (was GNU parallel und xargs tun)

Als Antwort des Benutzers funktioniert dieser Code gut, außer dass er keine letzte URL verarbeitet

urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) && echo "$url $urlstatus" >> urlstatus.txt & 

Vielleicht fügen Sie wait help hinzu, irgendwelche Vorschläge

3
Sie könnten dazu in Unterprozesse nachsehen. Das bedeutet, dass Sie für jede "Curl" eine eigene Shell / einen Thread starten könnten. Was Ihre Lösung mit xargs / parallel anbelangt, lohnt es sich, diese hinzuzufügen, da Sie möglicherweise etwas falsch gemacht haben. Das Lesen der Datei sollte schnell genug sein (außer wenn sie wirklich groß ist), aber das Warten auf die Antwort ist wahrscheinlich das, was Ihr Problem ist. Seth vor 7 Jahren 0
Nach der Verwendung von parallel verarbeitet es eine einzelne URL wie das normale Bash-Skript. user7423959 vor 7 Jahren 0
Warum sollte eine einzelne URL schneller sein? Mit einer einzigen URL können Sie die gewünschte Parallelisierung vornehmen, es wird nicht schneller. Mit mehreren URLs auf der anderen Seite können Sie gleichzeitig eine Reihe von URLs anfordern. Das Problem könnte also gewesen sein, wie Sie Parallelen aufgerufen / verwendet haben. Daher könnte es nützlich sein, anzugeben, wie Sie es tatsächlich versucht haben. Seth vor 7 Jahren 0
hier ist beispiel --cat abc.txt | parallel -j100 --pipe /root/bash.sh abc.txt Sie haben jetzt eine Idee ,,, und n1 wird auch verwendet ,,, es verarbeitet zur Zeit eine URL, nicht gleich viel Zeit. user7423959 vor 7 Jahren 0

2 Antworten auf die Frage

3
me_alok

In bash können Sie das Symbol & verwenden, um Programme im Hintergrund auszuführen. Beispiel

for i in ; do echo $i>>numbers.txt & done; 

BEARBEITEN: Sorry, aber die Antwort auf Ihre Frage im Kommentar ist falsch. Ich habe die Antwort gerade bearbeitet. Vorschläge für Code

urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) && echo "$url $urlstatus" >> urlstatus.txt & 
Können Sie einen Vorschlag für den Code geben, da das Hinzufügen des Symbols (&) das Timing nicht verbessert. user7423959 vor 7 Jahren 0
Versuchen Sie diesen URL-Status = $ (curl -o / dev / null --silent --head --write-out '% ' "$ " --max-time 5) & me_alok vor 7 Jahren 0
schon versucht , user7423959 vor 7 Jahren 0
Das hat bei mir funktioniert. ninja vor 7 Jahren 0
Es funktioniert, ich habe es getestet, bevor ich die Antwort editierte me_alok vor 7 Jahren 0
Ihr Code funktioniert gut, aber ein Problem. Er verarbeitet nicht die letzte URL. Möglicherweise müssen Sie im Code irgendwo warten, irgendeinen Vorschlag dazu user7423959 vor 7 Jahren 0
es fehlt tatsächlich viel URL, nur einige werden angezeigt user7423959 vor 7 Jahren 0
Das Hinzufügen von wait am Ende der Datei funktioniert auch nicht user7423959 vor 7 Jahren 0
Es ist nicht notwendig, einen wait-Befehl hier hinzuzufügen, es sei denn, Sie möchten die Anzahl der Threads begrenzen und sollten sich innerhalb der while-Schleife befinden. me_alok vor 7 Jahren 0
Wie lautet die Ausgabe in urlstatus.txt für ein fehlendes URL-Problem? Fehlt nur der Statuscode oder die gesamte URL und der Status? me_alok vor 7 Jahren 0
URL fehlt insgesamt, deren Statuscode "000" lautet. Dies ist kein Problem. Ich möchte, dass die Thread-Kontrolle in diesem Skript sehr lange dauert, weil die Textdatei mein System für eine Weile aufhängt (obwohl Ergebnisse erzeugt werden). Alle Vorschläge zum Hinzufügen von Threading zu diesem Code user7423959 vor 7 Jahren 0
Können Sie eine Beispieleingabe und -ausgabe erstellen? me_alok vor 7 Jahren 0
Ja, die Ausgabe wird alle Vorschläge zur Thread-Steuerung in diesem Skript korrekt wiedergegeben user7423959 vor 7 Jahren 0
Können Sie eine Beispielausgabe posten (sowohl stdout als auch urlstatus.txt)? me_alok vor 7 Jahren 0
1. Hier ist die Eingabedatei http://s3.amazonaws.com/alexa-static/top-1m.csv.zip 2. Ich speichere Ihr Skript als bash.sh und führe es als Terminal aus ./bash.sh top1m. txt (entpacken oben) 4. dann werden die ergebnisse in urlstatus.txt-datei 5 erzeugt. ich möchte, dass in diesem skript (sie benötigen einige eingaben, um eine kleine datei zu testen) 6. es gibt viel mehr dateien, da dies groß ist ... es gibt wie 100, 500 kb usw. nicht so groß ist dies, 6. Ihre Antwort funktioniert, ich frage nur, ob eine Thread-Kontrolle möglich ist user7423959 vor 7 Jahren 0
Nun, hier funktioniert Multithreading. Verwenden Sie den Befehl 'top', um dies anzuzeigen. Lassen Sie mich zur Thread-Steuerung sehen, was ich tun kann me_alok vor 7 Jahren 0
1
Ole Tange

GNU parallel und xargs verarbeiten gleichzeitig eine Zeile (getestet)

Können Sie ein Beispiel dafür geben? Wenn Sie -jdann verwenden, sollten Sie in der Lage sein, mehr als einen Prozess gleichzeitig auszuführen.

Ich würde es so schreiben:

doit() { url="$1" urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) echo "$url $urlstatus" } export -f doit cat input.txt | parallel -j0 -k doit 

Basierend auf der input.txt:

Input file is txt file and lines are separated as ABC.Com Bcd.Com Any.Google.Com Something like this www.google.com pi.dk 

Ich bekomme die Ausgabe:

Input file is txt file and lines are separated as 000 ABC.Com 301 Bcd.Com 301 Any.Google.Com 000 Something like this 000 www.google.com 302 pi.dk 200 

Was ungefähr so ​​aussieht:

000 if domain does not exist 301/302 for redirection 200 for success 

Ich muss sagen, dass ich ein wenig überrascht bin, wenn die von Ihnen bereitgestellten Eingabezeilen tatsächlich Teile der von Ihnen verwendeten Eingabe sind. Keine dieser Domänen existiert, und Domänennamen mit Leerzeichen in werden wahrscheinlich niemals existieren - je:

Input file is txt file and lines are separated as Any.Google.Com Something like this 

Wenn Sie keine Eingaben aus Ihrer eigentlichen Eingabedatei gemacht haben, sollten Sie dies wirklich tun, anstatt sich etwas anzueignen - vor allem, wenn das erstellte Zeug nicht den echten Daten ähnelt.

Bearbeiten

Debuggen, warum es für Sie nicht funktioniert.

Bitte schreiben Sie kein Skript, sondern führen Sie dieses direkt im Terminal aus:

bash # press enter here to make sure you are running this in bash doit() { url="$1" urlstatus=$(curl -o /dev/null --silent --head --write-out '%' "$" --max-time 5 ) echo "$url $urlstatus" } export -f doit echo pi.dk | parallel -j0 -k doit 

Das sollte geben:

pi.dk 200 
hey, ich habe den gleichen Statuscode 000, können Sie mir sagen, wie Sie Ihr Skript vom Terminal aus ausführen, kann es helfen user7423959 vor 7 Jahren 0
Die Eingabezeilen habe ich oben in die Datei `input.txt` eingefügt. Dann führe ich genau die Zeilen aus, die oben geschrieben sind. Meine Schale ist Bash. Ole Tange vor 7 Jahren 0
Ich erkläre den gesamten Prozess - 1. Ich kopierte Ihr Bash-Skript und speicherte es als Bash.sh und erteilte Ausführungsberechtigungen. 2. Meine Eingabedatei ist eine große Datei, aber ich habe auch eine kleine Datei mit 10 Zeilen getestet. --- Hier ist die Liste www.yahoo.com, www.google.com facebook.com amazon.com bing.com apple.com www.microsoft. com www.windows.com ,,,,, alle nach Zeilen getrennt und als top.txt 4 gespeichert. jetzt gehe ich zum terminal und tippe ./bash.sh top.txt 5 ein. jetzt gibt es das ergebnis 000 in jeweils 6 jetzt können Sie mir weiterhelfen, wo ich falsch liege, danke user7423959 vor 7 Jahren 0
Das funktioniert gut user7423959 vor 7 Jahren 0