Hello!
Van egy ilyenem:
#!/bin/bash
maxjobs=10
running=0
while read host source target ; do
(ssh root@$host "./valamit-csinalunk $source $target") &
#(dd if=/dev/zero of=/dev/null bs=1000 count=1000000) &
#(echo "lofasz"; sleep 10 ) &
running=$(($running+1))
if [ "$running" -ge $maxjobs ]; then
wait
running=0
fi
done < replication.cfg
wait
Ez egy nagyon egyszeru dolog lenne arra, hogy bizonyos dolgokat parhuzamosan vegezzek el. Azt tapasztalom, hogy ha ott van az ssh barmilyen formaban a ciklusban, akkor a while ciklus $maxjobs utan kiszall. Ha barmi egyeb van ott (lasd kikommentezett utasitasok) akkor a program az elvarasoknak megfeleloen mukodik. Biztosan elsiklok valami trivialis dolog folott, de mi az?
Koszi!
- 6078 megtekintés
Hozzászólások
Biztos vagy benne, hogy az ssh parancsot al-shell-ben akarod a háttérben futtatni? szerintem első körben vedd ki körüle a kerek zárójeleket. (Értem, hogy a többit is úgy próbáltad, de azért .. )
- A hozzászóláshoz be kell jelentkezni
Anélkül kezdtem, a zárójelezés már a szenvedés része, meg kiírattam benne még dolgokat.
- A hozzászóláshoz be kell jelentkezni
Na. Így működik:
#!/bin/bash
maxjobs=10
running=0
doit() {
while read host source target ; do
ssh root@$host "./valamit-csinalunk $source $target" &
running=$(($running+1))
if [ "$running" -ge $maxjobs ]; then
wait
running=0
fi
done
}
cat replication.cfg | doit
wait
(ha esetleg hiba van, az azért, mert csak átírtam itt a hupon a lényeget, az eredeti script jóval bonyibb)
Vajon mi erre a magyarázat?
- A hozzászóláshoz be kell jelentkezni
A pipe elve egy subshell, most azt csinálod, mintha ezt csinálnád:
cat replication.cfg | while read host source target; do ...
- A hozzászóláshoz be kell jelentkezni
Az ssh nem ad visszatérési értékat, amíg a kapcsolat be nem fejeződik, vagy le nem választja magát a shell -ről, így a nohup sem hajtódik végre.
Azt próbáld, hogy az ssh -t minusz-kis-ef kapcsolóval indítod, tehát így:
ssh -f user@host
U.I.: Különben mi lesz ez?
----
올드보이
http://molnaristvan.eu/
- A hozzászóláshoz be kell jelentkezni
Hol van nohup az eredetiben? Simán van egy (több) háttérben indított ssh.
- A hozzászóláshoz be kell jelentkezni
A parancs végén a & nohup -ot küld azzal indítja a subshell -t
----
올드보이
http://molnaristvan.eu/
- A hozzászóláshoz be kell jelentkezni
Noha a megfogalmazás erősen messze van a valóságtól, így már értem mit akartál mondani.
- A hozzászóláshoz be kell jelentkezni
Ezt elmagyarázhatnád, én ezt így tudom...
ha tévednék szívesen venném, ha felvilágosítanál
----
올드보이
http://molnaristvan.eu/
- A hozzászóláshoz be kell jelentkezni
Ezt írtad: "a & nohup -ot küld azzal indítja a subshell". Én meg ezt: "a *megfogalmazás* erősen messze van a valóságtól". Szóval, most történelemóra következik:
régen, még az eredeti Bourne-shell idejében, mikor egy parancsot háttérben indítottunk és nem volt átirányítás a parancssorban, akkor az (a shell) még gyönyörűen kommunikált az eredeti stdin/stdout-tal, azaz a terminállal. (Az volt a szép idő, amikor egy háttérprocessz elkapkodta az előtérben futó shell elől az inputot.) Ezért is volt nagyon fontos az átirányítás. Ha pedig az ember Ctrl-D-vel/exittel kilépett a (fő)shellből, akkor a shell *küldött* egy HUP-szignált a háttérprocessz(ek)nek. Ettől az általában megdeglett. Ha ezt az ember nem akarta, akkor kellett "nohup parancs & " formában indítani. Mőködése: a nohup parancs elindult háttérben, beállította a *saját* környezetét úgy, hogy ignorálta a HUP-szignált, majd exec-cel elindította a paraméterként megadott parancsot maga helyett. Eredménye, mivel a SIGIGN öröklődik exec-nél, a valójában futó parancs is ignorálta a HUP-ot, így képes volt tovább futni, amikor az eredeti (szülő) shell kilépett (az ugyanis hiába küldött neki megszakítást). Valamikor (én egy korai Korn-shell-re tippelek, de nem tudom) aztán lett annyi előrelépés, hogy ha "parancs &" formájú futtatás történik (nohup nélkül akár), akkor a shell maga a gyerekprocesszre beállítja ezt a SIGIGNORE-t a hup-megszakításra. Tehát nem *küldi* a shell a nohup-ot, hanem beállítja a hup-megszakításra érzéketlenséget. (Az csak hab a tortán, hogy úgy tudom, ettől függetlenül küldi azt a szerencsétlen HUP-ot exit-nél.)
- A hozzászóláshoz be kell jelentkezni
Áhán így már értem! Köszönöm, most megint tanultam valamit.
----
올드보이
http://molnaristvan.eu/
- A hozzászóláshoz be kell jelentkezni
A ksh-ban 'set -o'-val a bash-ben pedig 'shopts'-sal allithato a 'huponexit' parameter (kuldjon HUP ot a gyerekeinek avagy sem exit eseten). Szvsz csak a 'default' valtozott 'yes'-ről 'no'-ra.
Hogy ez elorelepes-e, az persze kerdeses. ;)
- A hozzászóláshoz be kell jelentkezni
Bash-ben shopt (egyesszám) a parancs neve, a ksh-val meg az a baj, hogy a gépemen se a ksh93-nak, sem a pdksh-nak nem létezik ilyen opciója. Milyen ksh-verzióban találtad ezt? Eseteg az se ksh, hanem mondjuk zsh? (Bár ez utóbbira meggyőző érveket nem találtam egy gyors guglizással.)
- A hozzászóláshoz be kell jelentkezni
Bocs, fejbol irtam a 'nagyjabol jo' hozzaszolast.
a pdksh-ban 'nohup' az opcio neve.
echo $KSH_VERSION
@(#)PD KSH v5.2.14 99/07/13.2
- A hozzászóláshoz be kell jelentkezni
Ezeket nézegesd meg, szerintem mindenre találsz bennük választ:
http://code.google.com/p/ppss/
http://drdobbs.com/go-parallel/article/showArticle.jhtml?articleID=2158…
http://ubuntuforums.org/showthread.php?t=31339
http://librenix.com/?inode=6383
http://ftp.gnu.org/gnu/parallel/
http://ftp.gnu.org/gnu/pexec/
http://pebblesinthesand.wordpress.com/2008/05/22/a-srcipt-for-running-p…
http://hup.hu/node/101482
- A hozzászóláshoz be kell jelentkezni
- A hozzászóláshoz be kell jelentkezni
Ebben a témában még ezeket tudom ajánlani, a második az első párhuzamos változata:
http://docs.fabfile.org/
http://tav.espians.com/fabric-python-with-cleaner-api-and-parallel-depl…
És ez is Python-ban van írva + a sudo-zást nagyon jól kezeli :)
- A hozzászóláshoz be kell jelentkezni
Akinek esetleg azonnal kell:
https://build.opensuse.org/package/show?package=pssh&project=home%3Ahor…
- A hozzászóláshoz be kell jelentkezni
Debian ill ubuntu alatt: `apt-get install pexec`, egyebkent forrasbol is. Ha van publikus kulcsos ssh-d, akkor azt is, maga'tol. (Igen, kis o"nreklam, node pont eme dolgokat potolta a maga idejeben...).
- A hozzászóláshoz be kell jelentkezni
Hi!
Köszönöm a válaszokat, de félreértettétek a dolgot. Természetesen az említett tool-okat, módszereket ismerem, a feladatot bárhogy meg lehet oldani, de itt ráfutottam egy -számomra- érdekességnek tűnő dologra, amit szeretnék megérteni. Egyébként az egyik link: http://pebblesinthesand.wordpress.com/2008/05/22/a-srcipt-for-running-p… pontosan ugyanaz, mint az enyém és hasonlóképp viselkedik.)
Kifejezetten az érdekelne, hogy a lenti 3 dolog közül,
1. http://pastebin.com/wLJTusu6
2. http://pastebin.com/bFtnAJ4v
3. http://pastebin.com/1FzbE660
egy több ezer soros replication.txt inputtal az 1. miért fejeződik be $maxjobs után, ha a 2. változat nem és a 3. sem.
- A hozzászóláshoz be kell jelentkezni
Igen. az `ssh` kliens valamit csinal a terminallal, amit a szu"lo" (bash) nem vesz jo'ne'ven. Nem tudom pontosan mie'rt, de a
< /dev/null
atiranyitas megszu"nteti a proble'ma't, ugy szepen szokatak menni ezek a dolgok, meg most az altald irt (nyito) peldadat is megoldja. A fentebb linkelt 3-as peldaban is azert oldja meg a kozvetett fuggvenyezes, mert ugy az ssh stdin-je nem egy tty lesz, hanem a cat pipe-ja.
Amit viszont nem ertek, hogy a ptty allokaciot (buzeralast) ki lehet kapcsolni az ssh -T kapcsoloja'val; viszont onmagaban az sem oldja meg az eredeti problemat.
Talan egy strace/ltrace kozelebb vinne a megoldashoz, hha me'g -T-vel is raenged valami olyan termios-os vagy egyeb ioctl()-es dolgot az fd0-ra, amiert a bash azt mondja hogy bocs.
A.
- A hozzászóláshoz be kell jelentkezni
Közben debuggoltam, a bash nem azt mondja hogy bocs, hanem simán egyszerűen az ssh flusholja az stdin-t a session _végén_. Így logikus, hogy miért tud ez megtörténni a while < file esetben és nem a másikban. És nem $maxjobs -szor megy le a ciklus, az csak egy sajátosság volt a futások hossza miatt. :)
Bevallom csak akkor kezdtem ebben az irányban nézelődni, amikor kicseréltem a bash-t default solaris sh-ra (bash gyakrabban szokott meglepni), az ssh-t meg rsh-ra.. ja, az rsh is flusholja a stdint :)
- A hozzászóláshoz be kell jelentkezni
Hm, itt ennel a ciklusnal mit definal(sz) session-nak? Es kerdes, hogy hogyan lehet az stdin-t flush-olni? A tobbi vilagos :] De hogy flush+stdin? rai'r (write()...?) az stdin-re? vagy tcflush()-ra gondolsz, ami mondjuk egy fokkal ma'r (p)tty specifikusabb egy allatfaj?
- A hozzászóláshoz be kell jelentkezni
session alatt az ssh sessiont értettem. Elnézést, nem voltam elég specifikus, terminál specifikus ioctl hívást használ :)
- A hozzászóláshoz be kell jelentkezni
Hát én ezt futtattam, de nem sikerült reprodukálnom az említett viselkedést: http://pastebin.com/JW8qTh13
A yes.txt-ben 'y'-ok voltak soronként.
Másrészt kérlek fejtsd ki részletesebben amit írtál itt, mert nagyon érdekelne, de nem értem. (Ez valsz az én hibám, de a tényen nem változtat.)
- A hozzászóláshoz be kell jelentkezni
Szerintem ne localhost-ra ssh-zz, hanem egy lassabban elérhető gépre.
- A hozzászóláshoz be kell jelentkezni
Betettem egy sleep 2 az ls mögé és meghalt, a wait volt az utolsó parancs ami futott mielőtt kilépett.
- A hozzászóláshoz be kell jelentkezni
Esetleg egy stty -a az ssh előtt/után?
- A hozzászóláshoz be kell jelentkezni
Write only mód, itt az én megoldásom:
Nem a processek számát figyelem, hanem hogy ráér-e a cpu, de ez tökmindegy. Egy, a scriptben definiált függvényt hívok meg, és jónapot.
Viszont szerintem ez se oldja meg a gondodat.... bosszantó.
Igen, az ssh kavarja el, eheh, man ssh:
-n Redirects stdin from /dev/null (actually, prevents reading from stdin).
Ja, most látom, hogy erre már rájöttetek, bocs...
- A hozzászóláshoz be kell jelentkezni
ott a pont a -n opcióval, így én bemásolom a következő sort is a man-ból:
-n Redirects stdin from /dev/null (actually, prevents reading from
stdin). This must be used when ssh is run in the background.
problem solved, egyedül Fisher tud olvasni az itt megszólalók közül. (Engem is beleértve, mert én is csak ennek hatására néztem bele.)
- A hozzászóláshoz be kell jelentkezni
Rsh-nak is van ilyenje: (okulásként)
-n Redirect the input of rsh to /dev/null. You
sometimes need this option to avoid unfor-
tunate interactions between rsh and the shell
which invokes it. For example, if you are
running rsh and invoke a rsh in the back-
ground without redirecting its input away
from the terminal, it blocks even if no reads
are posted by the remote command. The -n
option prevents this.
Ma is okosabb lettem, thx all! Igazából a |while és a while< közti különbséget nem fogtam fel.
- A hozzászóláshoz be kell jelentkezni
Azt nem tudom, hogy mi az oka annak, hogy a 0-ás descriptor a pipe-os változatnál /dev/null az ssh processz esetében,
de emiatt van az, hogy az egyik működik a másik nem.
Szóval a pipe-os verziónál más lesz az stdin ezért nem "eszi meg" az input-ot.
A /proc/PID/fd -t listáztam itt.
pipe -al:
- valamelyik ssh process:
lr-x------ 1 user user 64 2011-10-21 00:58 0 -> /dev/null
lrwx------ 1 user user 64 2011-10-21 00:58 1 -> /dev/pts/0
lrwx------ 1 user user 64 2011-10-21 00:58 2 -> /dev/pts/0
lr-x------ 1 user user 64 2011-10-21 00:58 3 -> socket:[969279]
lrwx------ 1 user user 64 2011-10-21 00:58 5 -> /dev/pts/0
lrwx------ 1 user user 64 2011-10-21 00:58 6 -> /dev/pts/0
- ./test.sh -hoz tartozó bash
lrwx------ 1 user user 64 2011-10-21 00:59 0 -> /dev/pts/0
lrwx------ 1 user user 64 2011-10-21 00:59 1 -> /dev/pts/0
lrwx------ 1 user user 64 2011-10-21 00:58 2 -> /dev/pts/0
lr-x------ 1 user user 64 2011-10-21 00:59 255 -> /home/user/Desktop/test.sh
- cat valami.txt | doit által nyitott shell:
lr-x------ 1 user user 64 2011-10-21 00:59 0 -> pipe:[968361]
lrwx------ 1 user user 64 2011-10-21 00:59 1 -> /dev/pts/0
lrwx------ 1 user user 64 2011-10-21 00:58 2 -> /dev/pts/0
pipe nélkül:
- valamelyik ssh process:
lr-x------ 1 user user 64 2011-10-21 00:39 0 -> /home/user/Desktop/yes.txt
lrwx------ 1 user user 64 2011-10-21 00:39 1 -> /dev/pts/0
l-wx------ 1 user user 64 2011-10-21 00:39 2 -> /dev/pts/0
lr-x------ 1 user user 64 2011-10-21 00:39 3 -> socket:[915716]
lrwx------ 1 user user 64 2011-10-21 00:39 5 -> /dev/pts/0
l-wx------ 1 user user 64 2011-10-21 00:39 6 -> /dev/pts/0
- ./test.sh -hoz tartozó bash
r-x------ 1 user user 64 2011-10-21 00:40 0 -> /home/user/Desktop/yes.txt
lrwx------ 1 user user 64 2011-10-21 00:40 1 -> /dev/pts/0
lrwx------ 1 user user 64 2011-10-21 00:40 10 -> /dev/pts/0
l-wx------ 1 user user 64 2011-10-21 00:39 2 -> /dev/pts/0
lr-x------ 1 user user 64 2011-10-21 00:40 255 -> /home/user/Desktop/test.sh
- A hozzászóláshoz be kell jelentkezni
Mert a pipe jobb oldalára indít egy subshell-t:
http://hup.hu/node/107961#comment-1362615
Gondolom én. Elég sok irományt találtam googléval, amik ezt problémát boncolgatják.
- A hozzászóláshoz be kell jelentkezni
Subshell miatt még nem feltétlenül (én is próbáltam berakni subshellbe).
Megnéztem több gépen, oprendszeren, és arra jutottam hogy teljesen implementáció és időjárásfüggő: van, ahol a while< -al is úgy megy, ahogy kéne, van, ahol pipe-al se. :)
- A hozzászóláshoz be kell jelentkezni
Hát a válasz a forráskódban megtalálható (bash 4.2, execute_cmd.c 1431. és 493. sor):
/* If this is a user subshell, set a flag if stdin was redirected.
This is used later to decide whether to redirect fd 0 to
/dev/null for async commands in the subshell. This adds more
sh compatibility, but I'm not sure it's the right thing to do. */
if (user_subshell)
{
stdin_redir = stdin_redirects (command->redirects);
restore_default_signal (0);
}
/* If this is an asynchronous command (command &), we want to
redirect the standard input from /dev/null in the absence of
any specific redirection involving stdin. */
if (should_redir_stdin && stdin_redir == 0)
async_redirect_stdin ();
async_redirect_stdin ()
{
int fd;
fd = open ("/dev/null", O_RDONLY);
if (fd > 0)
{
dup2 (fd, 0);
close (fd);
}
else if (fd < 0)
internal_error (_("cannot redirect standard input from /dev/null: %s"), strerror (errno));
}
Szóval ha egy subshell-ről van szó, az indított parancs a háttérben van futtatva (&)
és át van irányítva az stdin-je a futtató shell-nek, akkor a bash még mielőtt elindítaná az ssh-t beállítja az stdin-t /dev/null-ra.
sh kompatibilitás miatt :]
Ez látszik az strace-ből is.
- A hozzászóláshoz be kell jelentkezni
Azt hiszem, az "I'm not sure it's the right thing to do" résszel egyetértek.
$ (readlink /proc/self/fd/0 &)
/dev/null
$ (readlink /proc/self/fd/0 &) <&0
/dev/pts/0
- A hozzászóláshoz be kell jelentkezni