Behöver hjälp med ett bash skript

Permalänk

Behöver hjälp med ett bash skript

Hejsan allihop

Jag behöver hjälp med ett bash skript.

Tanken med skriptet är att det skall ladda hem hemsidor.

Jag tänkte mig som så att jag börjar med att göra en lista på alla sidor som skall laddas hem. Därefter så använder jag wget för att ladda hem alla dessa hemsidor.

Problemmet är att jag vill att en wget prosses skall startar för varje hemsida som skall laddas ner parallellt istället för att en sida laddas hem i taget.

Något som skulle vara ännu bättre skulle vara att alla filerna ifrån varje hemsida skulle kunnas laddas hem parallel.

Jag skulle vilja att skriptet skall vara multitrådat så att alla min prosesser kan arbeta med skriptet samtidigt.

Jag hoppas att jag har gjort mig själv förstod och hoppas att få svart snart

Tack på förhand

Permalänk
Medlem

Om du har adresserna i en fil, en adress per rad så kan du loopa över dem med

while read url; do do_whatever $url done < url-list

$url kommer för varje iteration att innehålla adressen.

Om du inte har några krav på att sidan skall hämtas om om fel uppstår och liknande så kan du ju helt enkelt fyra av wget ... & i loopen (& gör att programmet körs i bakgrunden).

Permalänk
Medlem

Vad finns det för anledning till ladda ner dem parallellt?
Det finns heller ingen anledning till att dela upp belastningen på flera processorer då de inte belastas, din nätverksanslutning och hårddisk är dina flaskhalsar.

Som NakedApe sa så använd wget ... & för att köra processen i bakgrunden om du nu måste köra dem parallellt.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Lonsas
Vad finns det för anledning till ladda ner dem parallellt?
Det finns heller ingen anledning till att dela upp belastningen på flera processorer då de inte belastas, din nätverksanslutning och hårddisk är dina flaskhalsar.

Kanske om du drar filer från SUNet eller liknande, men de flesta servrar brukar ha en limit på någon MB per session. Sitter man med en hyffsad lina så kan man dra många parallella hämtningar innan disk eller uppkoppling blir en flaskhals.

Permalänk

Tack så mycket för era svar.

Precis som nillon skriver så finns det servrar med en limit per session. dock så finns det är annan anledning till att jag vill köra parallellt . Med wget så kan man bara ladda hem en fil i taget från samma adress. om det finns sidor med hundratals filer på 1k storlek så kommer dessa ta ett tag ioch med att en process kan bara var så pass snabb.
Så jag skulle vilja ha något i stil med att wget listar alla filer från den adressen och därefter så startar den en process per fil som skall laddas hem. På det sättet kommer dessa filer laddas hem mycket snabbare än om wget laddar hem en fil i taget.
Det jag vill åstadkomma är att ladda ner sidorna på kortast möjliga tid.
Därför måste det köras parallellt.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Mysticsam
Så jag skulle vilja ha något i stil med att wget listar alla filer från den adressen och därefter så startar den en process per fil som skall laddas hem. På det sättet kommer dessa filer laddas hem mycket snabbare än om wget laddar hem en fil i taget.

Det låter ju mer som om du letar efter en web crawler av något slag. Tyvärr har jag inget förslag på lämplig mjukvara så här på rak arm då det var många år sen jag hade behov av något liknande. Det finns ett embryo till den här funktionaliteten i wget, släng ett öga på --input-file och --spider men du vill antagligen ha något lite mer kompetent. Wikipedia har en lista på fria alternativ här och Google/Freshmeat/etc kan säkert hitta fler.

Permalänk

Tack för tipset

Permalänk

Hejsan allihopa nu återanvänder jag denna tråd för ett annat problem jag har.

Det är nämligen så att jag har en 4-kärnig processor (q6600).

och jag vill köra detta skriptet :

#!/bin/bash for d in {{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}} ;do echo $d>> test.txt;done exit 0

Vilket går bra men det kör bara på en av mina fyra kärnor vilket gör att det skriptet tar lång tid att köra.

Hur gör jag för att dela upp lasten mellan mina fyra kärnor och så att alla kärnor arbeta hela tiden?

Skriptet måste vara i bash.

Tack på förhand

Permalänk
Medlem

Varning för en bristfälligt testad och "smutsig" lösning, jag är säker på att man kan lösa det elegantare än såhär, till och med i bash...

Men här är iallafall ett grovt utkast som kanske kan ge dig lite idéer om inte annat.

#! /bin/bash if [ "$(basename $0)" = "child" ]; then for idx in {{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}; do echo $2$idx >> $1 done exit 0 else MAX_CHILD_PROCS=4 OUT_FILE="$(mktemp /tmp/$(basename $0).XXXX)" for idx in {{a..z},{A..Z},{0..9}}; do ./child $OUT_FILE $idx & count=$(($count + 1)) if [ $count -ge $MAX_CHILD_PROCS ]; then wait count=$((count - 1)) fi done while [ $count -gt 0 ]; do wait count=$((count - 1)) done if [ "x$1" = "x" ]; then sort $OUT_FILE else sort -o $1 $OUT_FILE fi rm -f $OUT_FILE fi

Skriptet kräver ett "trick" och det är att du skapar en symbolisk länk till det som heter "child" i samma katalog. Säg att du sparar skriptet som foo så kör du ln -s ./foo child för att skapa länken.
Anropa skriptet utan argument för att få sorterad output på STDOUT eller med ett filnamn som argument för att få sorterat output i en fil. Om du inte vill ha resultatet sorterat kan du förenkla skriptet genom att skippa mellanlagringen i tempfil.
Antalet samtidiga processer du vill köra och "child"-skriptets namn kan du också ändra i skriptet men hur lämnas som en övning åt läsaren. Att ändra sorteringsordningen kan väl betraktas som överkurs.

EDIT: Märk väl att skriptet inte använder någon synkronisering av output. Det fungerar på min dual quad men det är också alla garantier du får.
Bash är inte rätt verktyg för sånt här.
En tänkbar lösning om du får problem med output i tempfilen är att skapa en tempfil per process (baserad på indexet den jobbar med t.ex.) och sedan slå ihop dessa (se cat(1) för mer info) när alla "trådar" kört klart och sortera den resulterande filen.