script mac create linux bash macos daemon

mac - create daemon linux bash



¿Cómo puedo iniciar un nuevo proceso que NO es un elemento secundario del proceso original? (5)

(OSX 10.7) Una aplicación que usamos nos permite asignar scripts para ser llamados cuando ciertas actividades ocurren dentro de la aplicación. He asignado un script de bash y se está llamando, el problema es que lo que tengo que hacer es ejecutar algunos comandos, esperar 30 segundos y luego ejecutar algunos comandos más. Si tengo mi script de bash, hago "dormir 30" y la aplicación se congela durante 30 segundos mientras espero a que termine mi script.

Intenté poner la espera de 30 segundos (y el segundo conjunto de comandos) en una secuencia de comandos separada y llamar a "./secondScript &", pero la aplicación todavía permanece allí durante 30 segundos sin hacer nada. Asumo que la aplicación está esperando a que finalice el script y todos los procesos secundarios .

He intentado estas variaciones para llamar al segundo script desde el script principal, todos tienen el mismo problema:

  • nohup ./secondScript &
  • ((./secondScript &) &)
  • (./secondScript &)
  • script nohup -q / dev / null secondScript &

No tengo la capacidad de cambiar la aplicación y decirle que inicie mi script y que no espere a que se complete.

¿Cómo puedo iniciar un proceso (preferiría que el proceso sea en un lenguaje de scripting) para que el nuevo proceso no sea un elemento secundario del proceso actual?

Gracias chris

ps probé el comando "disown" y tampoco ayudó. Mi guión principal se ve así:

[initial commands] echo Launching second script ./secondScript & echo Looking for jobs jobs echo Sleeping for 1 second sleep 1 echo Calling disown disown echo Looking again for jobs jobs echo Main script complete

y lo que obtengo por salida es esto:

Launching second script Looking for jobs [1]+ Running ./secondScript & Sleeping for 1 second Calling disown Looking again for jobs Main script complete

y en este punto, la aplicación que llama permanece allí durante 45 segundos, a la espera de que termine el segundo script.

pps

Si, en la parte superior del script principal, ejecuto "ps", lo único que devuelve es el ID de proceso de la sesión de bash interactiva que he abierto en una ventana de terminal separada.

El valor de $ SHELL es / bin / bash

Si ejecuto "ps -p $$" me dice correctamente

PID TTY TIME CMD 26884 ?? 0:00.00 mainScript

Si ejecuto "lsof -p $$" me da todo tipo de resultados (no pegué todas las columnas aquí suponiendo que no son relevantes):

FD TYPE NAME cwd DIR /private/tmp/blahblahblah txt REG /bin/bash txt REG /usr/lib/dyld txt REG /private/var/db/dyld/dyld_shared_cache_x86_64 0 PIPE 1 PIPE -> 0xffff8041ea2d10 2 PIPE -> 0xffff 8017d21cb 3r DIR /private/tmp/blahblah 4r REG /Volumes/DATA/blahblah 255r REG /Volumes/DATA/blahblah


Aqui tengo una concha

└─bash(13882)

Donde empiezo un proceso como este:

$ (urxvt -e ssh somehost&)

Obtengo un árbol de proceso (esta salida se cortó de pstree -p ):

├─urxvt(14181)───ssh(14182)

donde el proceso se controla debajo de pid 1 ( systemd en mi caso).

Sin embargo, si hubiera hecho esto (note donde está & ):

$ (urxvt -e ssh somehost)&

entonces el proceso sería un hijo del shell:

└─bash(13882)───urxvt(14181)───ssh(14182)

En ambos casos, el indicador de comandos de shell se devuelve inmediatamente y puedo exit sin finalizar el árbol de procesos que inicié anteriormente.

Para este último caso, el árbol de proceso se reparte debajo de pid 1 cuando el shell sale, por lo que termina igual que el primer ejemplo.

├─urxvt(14181)───ssh(14182)

De cualquier manera, el resultado es un árbol de procesos que sobrevive al shell. La única diferencia es la crianza inicial de ese árbol de procesos.

Para referencia, también puede utilizar

  • nohup urxvt -e ssh somehost &
  • urxvt -e ssh somehost & disown $!

Ambos dan el mismo árbol de proceso que el segundo ejemplo anterior.

└─bash(13882)───urxvt(14181)───ssh(14182)

Cuando se termina el shell, el árbol de procesos, como antes, se reparte a pid 1.

nohup además redirige la salida estándar del proceso a un archivo nohup.out , por lo que, si ese es un rasgo útil, puede ser una opción más útil.

De lo contrario, con el primer formulario anterior, inmediatamente tiene un árbol de procesos completamente separado.


Creo que depende de cómo su proceso principal intente detectar si su proceso secundario ha finalizado. En mi caso (mi proceso padre fue gnu make), tengo éxito al cerrar stdout y stderr (ligeramente basado en la respuesta de ese otro tipo ) de la siguiente manera:

sleep 30 >&- 2>&- &

También puede cerrar stdin

sleep 30 <&- >&- 2>&- &

o adicionalmente rechazar el proceso de su hijo (no para Mac)

sleep 30 <&- >&- 2>&- & disown

Actualmente probado solo en bash en kubuntu 14.04 y Mac OSX.


La forma típica de hacer esto en Unix es doblar la horquilla. En bash, puedes hacer esto con

( sleep 30 & )

(..) crea un proceso secundario y & crea un proceso de nieto. Cuando el proceso hijo muere, el proceso de nieto es heredado por init.

Si esto no funciona, entonces su aplicación no está esperando procesos secundarios.

Otras cosas que puede estar esperando incluyen la sesión y los archivos de bloqueo abiertos:

Para crear una nueva sesión, Linux tiene un setsid . En OS X, es posible que pueda hacerlo a través de un script , que por cierto también crea una nueva sesión:

# Linux: setsid sleep 30 # OS X: nohup script -q -c ''sleep 30'' /dev/null &

Para encontrar una lista de descriptores de archivos heredados, puede usar lsof -p yourpid , que generará algo como:

sleep 22479 user 0u CHR 136,32 0t0 35 /dev/pts/32 sleep 22479 user 1u CHR 136,32 0t0 35 /dev/pts/32 sleep 22479 user 2u CHR 136,32 0t0 35 /dev/pts/32 sleep 22479 user 5w REG 252,0 0 1048806 /tmp/lockfile

En este caso, además de las FD estándar 0, 1 y 2, también tiene un fd 5 abierto con un archivo de bloqueo que el padre puede estar esperando.

Para cerrar fd 5, puede usar exec 5>&- . Si crees que el archivo de bloqueo podría ser stdin / stdout / stderr, puedes usar nohup para redirigirlos a otra cosa.


Otra forma es abandonar al niño.

#!/bin/bash yourprocess & disown

Según tengo entendido, la aplicación reemplaza al shell bash normal porque todavía está esperando que finalice un proceso, incluso si init debería haberse ocupado de este proceso secundario. Podría ser que la " aplicación " intercepte el manejo de huérfanos que normalmente realiza init .

En ese caso, solo un proceso paralelo con algún IPC puede ofrecer una solución (vea mi otra respuesta)


Si todo lo demás falla:

  1. Crear una tubería con nombre

  2. inicie el script "lento" independiente de la " aplicación ", asegúrese de ejecutar su tarea en un bucle sin fin, comenzando con la lectura desde la tubería. Se volverá a bloquear cuando lea.

  3. Desde la aplicación, inicie su otro script. Cuando necesite invocar el script "lento", simplemente escriba algunos datos en la tubería. La secuencia de comandos lenta comenzará de forma independiente, por lo que la secuencia de comandos no esperará a que finalice la secuencia de comandos "lenta".

Entonces, para responder a la pregunta:
bash: ¿cómo puedo iniciar un nuevo proceso que NO es un elemento secundario del proceso original?

Simple: no lo inicie, pero deje que una entidad independiente lo inicie durante el arranque ... como init o sobre la marcha con el comando at o batch