[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: su - Unterschied sarge/etch



Wolf Wiegand:
>Friedhelm Usenet Waitzmann wrote:

>> Das würde in Sarge bedeuten, dass bei
>> 
>> $ su -c 'sleep 10'
>> 
>> der von su gestartete Prozess verwaist wäre, weil sein Erzeuger
>> (d.h. su) bereits gestorben wäre.  Welcher Prozess also sollte
>> auf das Ende von sleep warten können?  

>Die Shell.

Verstehe ich Dich richtig: Mit dem "Shell" meinst Du den
interaktiven Kommandointerpreter, in dem der Befehl
»su -c 'sleep 10'« eingegeben wurde.  Ja?

(Annahme:  Root hat als Shell bash eingestellt.)

Nachdem das »Shell« (PID=1000) das Programm su in einem
Unterprozess (PID=1001) gestartet hat, ist folgender Prozessbaum
A aufgebaut:

A:
PID  PPID
1000  999 »Shell«
1001 1000  \_ »su« »-c« »sleep 10«

>> Also käme der Aufruf von
>> su sofort zu Ende und nicht erst nach 10 Sekunden.  Das ist
>> allerdings nicht der Fall.

>Doch:

Ok, spielen wir das Szenario "su erzeugt einen Unterprozess,
wartet nicht auf seinen Tod sondern beendet sich selbst sofort"
mal durch:

Nun erzeugt Prozess 1001 einen Unterprozess 1002,

B:
PID  PPID
1000  999 »Shell«
1001 1000  \_ »su« »-c« »sleep 10«
1002 1001      \_ »su« »-c« »sleep 10«

der das Programm bash abzuarbeiten beginnt

C:
PID  PPID
1000  999 »Shell«
1001 1000  \_ »su« »-c« »sleep 10«
1002 1001      \_ »bash« »-c« »sleep 10« »bash«

Wenn sich das Programm su (Prozess 1001) , nachdem es den Prozess
1002 erzeugt hat, sofort beendet, ohne auf das Ende von 1002 zu
warten, ensteht folgende Situation D:

D:
PID  PPID
1000  999 »Shell«
1001 1000  \_ [defunct]
1002 1001      \_ »bash« »-c« »sleep 10« »bash«

Und da das »Shell« die von ihm erzeugten Unterprozesse beobachtet
und gestorbene mittels wait() beerdigt und init verwaiste
Prozesse adoptiert, ergibt sich Situation E:

E:
PID  PPID
1000  999 »Shell«
   1    0 »init«
1002    1  \_ »bash« »-c« »sleep 10« »bash«

Also: Mit der Beerdigung von 1001 wurde 1002 Waise und sofort vom
init (PID=1) adoptiert.  Also hat Prozess 1000 keine Möglichkeit
mehr, auf das Ende von Prozess 1002 zu warten.

Du beobachtest bei sarge aber etwas Anderes:  Das Programm sleep
ist Kindprozess des »Shell«.  Es kann somit nicht sein, dass su
(PID=1001) (aus Situation A heraus) einen Unterprozess (PID=1002)
erzeugt (Situation B), der dann mittels

   execl("/bin/bash", "bash", "-c", "sleep 10", "bash", NULL)
   
beginnt, den Kommandointerpreter bash zu betreiben (Situation C).

Ich vermute daher:  Statt dessen führt Prozess 1001 /selbst/

   execl("/bin/bash", "bash", "-c", "sleep 10", "bash", NULL)

aus, d.h., er hört auf, su abzuarbeiten, und beginnt das Programm
bash.  Es entsteht (aus Situation A heraus) folgender Prozessbaum
F (nur der Prozess 1001 ändert sich):

F:
PID  PPID
1000  999 »Shell«
1001 1000  \_ »bash« »-c« »sleep 10« »bash«

Nachdem nun Prozess 1001 das Programm bash begonnen hat, wird im
bash festgestellt, dass der Befehl »sleep 10« ein einfacher
Programmstart ist, und dass es darüberhinaus nach dem Ende von
sleep für das bash nichts Weiteres zu tun gibt.  In diesem Fall
ändert das bash den Befehl »sleep 10« stillschweigend um in
»exec sleep 10« und ersetzt sich deshalb mittels exec() durch
sleep; es wird kein Unterprozess erzeugt, der das Programm sleep
ausführt, und auf dessen Ende das bash dann noch warten müsste.
Im Prozessbaum verändert sich zum zweiten Mal also nur der
Prozess 1001:

G:
PID  PPID
1000  999 »Shell«
1001 1000  \_ »sleep« »10«

Diese Situation stimmt mit Deiner Beobachtung unter sarge
überein.

Dieses "Abkürzungsverhalten" von bash kannst Du mit

$ bash -x -c 'ps -p "$$" -f'

einerseits und

$ bash -x -c 'ps -p "$$" -f; :'

andererseits demonstrieren.

>wolf@sarge:~ $ su -c 'sleep 1000'
>Password: 

>[1]+  Stopped                 su -c 'sleep 1000'
>wolf@sarge:~ $ bg
>[1]+ su -c 'sleep 1000' &
>wolf@sarge:~ $ ps uax | egrep "([s]leep|[s]u)"
>root     30901  0.3  0.1  3132  560 pts/0    S    20:40   0:00 sleep 1000

Dass Du hier keinen Prozess mehr findest, der su abarbeitet,
heißt nicht, dass er sich beendet hat, sondern heißt nur, dass
der fragliche Prozess inzwischen sleep abarbeitet.

Beweis:

$ su -c 'set -x; ps -p"$$" -f; sleep 1000'
Password: 
UID        PID  PPID  C STIME TTY         TIME CMD
root      1001   999  0 xx:xx pts/0   xx:xx:xx sh -c set x; ...

[1]+  Stopped                 su -c 'set -x; ps -p"$$" -f; sleep 1000'

$ jobs -l %1
[1]+  1001 Stopped                 su -c 'set -x; ps -p"$$" -f; sleep 1000'

Du siehst: Die Prozessnummer in der von ps gelieferten
Prozessinfo stimmt mit der überein, die der Befehl »jobs -l«
liefert.  Also kann su keinen Unterprozess fork()ed haben.

-- 
Bitte in die Adressierung auch meinen |Please put my full name also into
Vor- u. Nachnamen stellen z.B.        |the recipient like
Friedhelm Waitzmann <xxx@example>, (Friedhelm Waitzmann) xxx@example,
"Waitzmann, Friedhelm" <xxx@example>



Reply to: