servicio script que iniciar ejecutar demonio crear como agregar python unix

python - script - iniciar daemon linux



¿Cuál es la razón para realizar una doble bifurcación al crear un daemon? (8)

Estoy tratando de crear un daemon en python. He encontrado la siguiente pregunta , que tiene algunos buenos recursos que actualmente estoy siguiendo, pero tengo curiosidad de por qué es necesario un doble tenedor. Recorrí google y encontré muchos recursos que decían que uno era necesario, pero no por qué.

Algunos mencionan que es para evitar que el daemon adquiera una terminal de control. ¿Cómo sería esto sin la segunda bifurcación? ¿Cuáles son las repercusiones?


Al mirar el código al que se hace referencia en la pregunta, la justificación es:

# Fork a second child and exit immediately to prevent zombies. This # causes the second child process to be orphaned, making the init # process responsible for its cleanup. And, since the first child is # a session leader without a controlling terminal, it''s possible for # it to acquire one by opening a terminal in the future (System V- # based systems). This second fork guarantees that the child is no # longer a session leader, preventing the daemon from ever acquiring # a controlling terminal.

Por lo tanto, es para asegurar que el daemon se vuelva a criar en init (solo en el caso de que el proceso que expulsa al daemon sea de larga duración), y elimina cualquier posibilidad de que el daemon recupere una tty controladora. Entonces, si ninguno de estos casos se aplica, entonces un tenedor debería ser suficiente. " Programación de red Unix - Stevens " tiene una buena sección sobre esto.


De acuerdo con "Programación avanzada en el entorno Unix", por Stephens y Rago, la segunda bifurcación es más una recomendación, y se hace para garantizar que el daemon no adquiera un terminal de control en los sistemas basados ​​en el sistema V.


Estaba tratando de entender el doble tenedor y tropecé con esta pregunta aquí. Después de mucha investigación esto es lo que descubrí. Con suerte, ayudará a aclarar las cosas mejor para cualquiera que tenga la misma pregunta.

En Unix, cada proceso pertenece a un grupo que a su vez pertenece a una sesión. Aquí está la jerarquía ...

Sesión (SID) → Grupo de procesos (PGID) → Proceso (PID)

El primer proceso en el grupo de proceso se convierte en el líder del grupo de proceso y el primer proceso en la sesión se convierte en el líder de la sesión. Cada sesión puede tener un TTY asociado. Solo un líder de sesión puede tomar el control de un TTY. Para que un proceso sea verdaderamente demonizado (se ejecuta en segundo plano), debemos asegurarnos de que el líder de la sesión muera, de modo que no haya posibilidad de que la sesión tome el control del TTY.

Ejecuté el programa de demonio de ejemplo de Python de Sander Marechal desde este sitio en mi Ubuntu. Aquí están los resultados con mis comentarios.

1. `Parent` = PID: 28084, PGID: 28084, SID: 28046 2. `Fork#1` = PID: 28085, PGID: 28084, SID: 28046 3. `Decouple#1`= PID: 28085, PGID: 28085, SID: 28085 4. `Fork#2` = PID: 28086, PGID: 28085, SID: 28085

Tenga en cuenta que el proceso es el líder de la sesión después de Decouple#1 , porque es PID = SID . Todavía podría tomar el control de un TTY.

Tenga en cuenta que Fork#2 ya no es el PID != SID líder de sesión PID != SID . Este proceso nunca puede tomar el control de un TTY. Verdaderamente demonizado.

Personalmente, encuentro que la terminología es dos veces confusa. Una mejor expresión idiomática podría ser tenedor-desacoplamiento-tenedor.

Enlaces de interés adicionales:


Estrictamente hablando, el doble tenedor no tiene nada que ver con volver a criar al daemon como hijo de init . Todo lo que es necesario para volver a criar al niño es que el padre debe salir. Esto se puede hacer con una sola horquilla. Además, hacer un doble tenedor por sí mismo no vuelve a parear el proceso del daemon para init ; el padre del daemon debe salir. En otras palabras, el padre siempre sale al bifurcar un daemon apropiado para que el proceso del daemon se vuelva a criar a init .

Entonces, ¿por qué el tenedor doble? POSIX.1-2008 Sección 11.1.3, " La Terminal de Control ", tiene la respuesta (énfasis añadido):

El líder de la sesión asigna la terminal de control para una sesión de una manera definida por la implementación. Si un líder de sesión no tiene un terminal de control y abre un archivo de dispositivo terminal que no está asociado a una sesión sin usar la opción O_NOCTTY (vea abrir ()), está definido por implementación si el terminal se convierte en el terminal de control de la sesión líder. Si un proceso que no es un líder de sesión abre un archivo de terminal, o la opción O_NOCTTY se usa en open (), entonces ese terminal no se convertirá en el terminal de control del proceso de llamada .

Esto nos dice que si un proceso daemon hace algo como esto ...

int fd = open("/dev/console", O_RDWR);

... entonces el proceso del daemon podría adquirir /dev/console como su terminal de control, dependiendo de si el proceso del daemon es un líder de la sesión, y dependiendo de la implementación del sistema. El programa puede garantizar que la llamada anterior no adquiera un terminal de control si el programa primero se asegura de que no sea un líder de sesión.

Normalmente, cuando se lanza un daemon, se llama a setsid (desde el proceso secundario después de llamar al fork ) para disociar el daemon de su terminal de control. Sin embargo, llamar a setsid también significa que el proceso de llamada será el líder de la sesión de la nueva sesión, lo que deja abierta la posibilidad de que el daemon pueda volver a adquirir una terminal de control. La técnica de doble bifurcación garantiza que el proceso del daemon no sea el líder de la sesión, lo que garantiza que una llamada a open , como en el ejemplo anterior, no dará como resultado que el proceso daemon recupere un terminal de control.

La técnica de doble horquilla es un poco paranoica. Puede que no sea necesario si sabe que el daemon nunca abrirá un archivo de dispositivo terminal. Además, en algunos sistemas puede no ser necesario incluso si el daemon abre un archivo de dispositivo terminal, ya que ese comportamiento está definido por la implementación. Sin embargo, una cosa que no está definida por la implementación es que solo un líder de sesión puede asignar el terminal de control. Si un proceso no es un líder de sesión, no puede asignar un terminal de control. Por lo tanto, si quiere estar paranoico y tener la certeza de que el proceso del daemon no puede adquirir inadvertidamente un terminal de control, independientemente de los detalles específicos de la implementación, entonces la técnica de doble horquilla es esencial.


La llamada de daemon () tiene la llamada primaria _exit () si tiene éxito. La motivación original puede haber sido permitir que el padre haga un trabajo extra mientras el niño está demonizando.

También puede basarse en la creencia errónea de que es necesario para garantizar que el daemon no tenga un proceso principal y se vuelva a crear para init, pero esto sucederá de todos modos una vez que el padre fallezca en el caso de una sola horquilla.

Así que supongo que todo se reduce a la tradición al final: una sola bifurcación es suficiente siempre y cuando el padre fallezca de todos modos.


Tomado de Bad CTK :

"En algunos sabores de Unix, se te obliga a hacer una doble horquilla en el arranque, para pasar al modo daemon. Esto se debe a que no se garantiza que el bifurcación individual se separe de la terminal de control".


Una discusión decente parece estar en http://www.developerweb.net/forum/showthread.php?t=3025

Citando a mlampkin desde allí:

... piense en la llamada setsid () como la "nueva" forma de hacer las cosas (desasociar del terminal) y el [segundo] tenedor () llamarlo después como redundancia para tratar con el SVr4 ...


Una razón es que el proceso principal puede esperar de inmediato wait_pid () para el niño y luego olvidarse de él. Cuando el nieto fallece, su padre es init, y lo esperará (y lo sacará del estado zombi).

El resultado es que el proceso principal no necesita estar al tanto de los niños bifurcados, y también permite bifurcar procesos de larga ejecución desde libs, etc.