ubuntuusers.de

Multi Threading auf Bash

Status: Gelöst | Ubuntu-Version: Ubuntu 7.10 (Gutsy Gibbon)
Antworten |

quorr

Anmeldungsdatum:
30. März 2008

Beiträge: 28

Hallo miteinander!

Ich wollte mal nachfragen, ob es nicht ein Bash Befehl oder ein Programm gibt, dass es ermöglicht viele gleiche Befehle auf mehrere Prozesse zu verteilen.
Ich stelle mir das so vor:

Liste von fertigen Befehlen in einer Datei z.B.:

Datei: dl
wget Datei1
wget Datei2
wget Datei3
...

wget ist hier nur ein Beispiel...

Diese Datei übergebe ich einem Programm:

thread -n 3 dl

Das erzeugt dann drei "Threads" in denen jeweils eine Zeile abgearbeitet wird. Wenn der eine Download beendet ist, holt sich der "Thread" die nächste Zeile.
Ich habe selbst schon versucht so etwas in Python zu schreiben, aber ich bekomme das leider nicht hin. (Ich habe das mit dem Threading in Python noch nicht so ganz verstanden...)

Vielen Dank für eure Hilfe!

adun Team-Icon

Avatar von adun

Anmeldungsdatum:
29. März 2005

Beiträge: 8606

Häng einfach ein & an die Befehle an, den werden dann jobs zugeordnet und sie bekommen einen eigenen 'process'. Ich denke du willst eher processe als Threads, das macht bei nem Download z.B. kaum Sinn.

quorr

(Themenstarter)

Anmeldungsdatum:
30. März 2008

Beiträge: 28

Das mit dem wget ist nur ein Beispiel. Ich hätte schon gerne Kontrolle über die Menge...
Ich weiß nicht, was passiert, wenn ich 500 "Prozesse" oder "Threads" auf einmal starte.

Ich habe oft solche Dinge wie beispielsweise Downloads, oder Konvertierungen von Videos oder Audiofiles, bei denen ich mehrfach (auf verschiedene Dateien) den gleichen Befehl ausführen muss.
Die lasten ja auch dementsprechend meistens immer einen Kern voll aus. Es geht eher darum, meinen QuadCore auszulasten in dem drei oder vier dieser Befehle parallel ausgeführt werden.

Ich bin mir nicht ganz sicher, ob man mein Anliegen jetzt besser versteht?

tux21b Team-Icon

Avatar von tux21b

Anmeldungsdatum:
15. August 2005

Beiträge: 1698

Wohnort: Linz.at

Ich verstehe dein Anliegen, aber wget ist dafür sicher kein gutes Beispiel. Obwohl, welche Internetverbindung hast du? Wieviel Netzwerkkarten?

Es ist aber sicher kein Problem, wenn du die Befehle gleichzeitig startest. 500 bekommst du sowieso nicht so schnell zusammen. Zum Beispiel wget: Such dir eine Datei, in die du die ganzen URLs einträgst, splitte diese auf mehrere kleine Dateien auf (z.B. 10) und starte dann 10 wget Prozesse, wobei du jedem die Datei mit den Links zum Downloaden übergibst)

Und damit die anderen Prozesse nicht blockiert werden, kannst du mit dem Befehl "nice" arbeiten.

Wenn du es aber wirklich so machen wie du beschrieben hast, hilft dir vllt das:

cat deinskript | awk '{ printf("%s &\n", $0) } NR % 4 == 0 { print "wait" }'


Das fügt überall ein & hinten an, damit alles im Hintergrund ausgeführt wird, und alle 4 Zeilen ein wait, damit vorher gewartet wird, bis die anderen Prozesse fertig sind. Ich finds sinnlos, aber es hilft dir vllt beim weiter experimentieren 😉

Gruß
Christoph

adun Team-Icon

Avatar von adun

Anmeldungsdatum:
29. März 2005

Beiträge: 8606

Prozesse kann der Kernel beliebig über die Kerne verteilen und der macht das eigentlich so wie es am Besten passt, man sollte ihm da nicht reinreden, es sei denn man hat gute Gründe. Prioritäten am Besten wie tux schon geschrieben hat über nice.
Je nachdem welche Shell du verwendest, bieten die diverse Möglichkeiten die Kindprozesse (aka jobs) zu überwachen. (Stichwort job control)

phst

Anmeldungsdatum:
24. Juni 2007

Beiträge: 527

quorr hat geschrieben:

Das mit dem wget ist nur ein Beispiel. Ich hätte schon gerne Kontrolle über die Menge...
Ich weiß nicht, was passiert, wenn ich 500 "Prozesse" oder "Threads" auf einmal starte.

Das System verteilt alle Threads gleichmäßig auf die Kerne, ohne dass du etwas dafür tun musst. Bei 500 Threads wird jedoch die Systemleistung ziemlich in die Knie gehen.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17622

Wohnort: Berlin

Mein erster Lösungsansatz von vorne mit der Tür ins Haus:
Im Pfad den Verteiler:

#!/bin/bash
# 
# verteiler.sh
#
ANZ=$1
for n in $(seq 1 $ANZ)
do
        ./callback.sh &
done


Und im lokalen Verzeichnis dann das ausführbare Script callback.sh beliebigen Inhalts, daß mit

verteiler.sh 500 


verteiler 500

Wenn aber callback.sh 500x neue Parameter braucht (wieso z.B. sollte man wget 3x mit gliechen Parametern aufrufen?) geht es nicht so leicht.

Widersprüchlich finde ich die Aussage:

Wenn der eine Download beendet ist, holt sich der "Thread" die nächste Zeile.


Gerade dann brauche ich doch keine unterschiedlichen Threads, wenn die Kommandos nacheinander laufen sollen.

Gleichzeitige Downloads dagegen können sehr wohl Sinn haben, wenn der eigene Downstream breiter ist als die einzelnen Server Daten spucken können.

dominator

Avatar von dominator

Anmeldungsdatum:
18. März 2008

Beiträge: 90

Wohnort: Meistens im Bierparadies Oberfranken

Wenn der eine Download beendet ist, holt sich der "Thread" die nächste Zeile.

Taskspooler [1] könnte einen Blick wert sein 💡

[1] http://vicerveza.homeunix.net/~viric/soft/ts/

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4694

Wohnort: Berlin

Die Optionen -n und -P von xargs können in einfachen Fällen auch hilfreich sein.

quorr

(Themenstarter)

Anmeldungsdatum:
30. März 2008

Beiträge: 28

Marc 'BlackJack' Rintsch hat geschrieben:

Die Optionen -n und -P von xargs können in einfachen Fällen auch hilfreich sein.

Genau das habe ich gesucht! Jetzt glüht der Prozessor!

Beispiel:
find . -name '*.wav' -print0 | xargs -0 -n 1 -P 4 lame -b 128 -m s

oder:
cat dl.txt | xargs -n 1 -P 4 wget

Ich möchte mich auch bei allen anderen für Ihre Hilfe bedanken!
Ich finde es immer wieder toll, eine so kompetente und nette Community im Rücken zu haben!

8) Weiter so!

Antworten |