Avvio di uno script come un altro utente


12

Ho creato uno script in /etc/init.d/ che deve eseguire diversi altri script da altri utenti (con privilegi non root) dalle loro directory home, come se li avessero avviati.

Lancio questi script con: sudo -b -u <username> <script_of_a_particular_user>

E funziona Ma per ogni script utente che continua a essere eseguito (ad esempio un po 'di watchdog) vedo un processo sudo parent corrispondente, ancora attivo e in esecuzione come root. Questo crea un pasticcio nell'elenco dei processi attivi.

Quindi la mia domanda è: come posso avviare (fork) un altro script dallo script bash esistente come un altro utente e lasciarlo come un processo orfano (autonomo)?

Spiegazione più dettagliata:
fondamentalmente sto cercando di fornire ad altri utenti sulla macchina un mezzo per eseguire roba all'avvio o allo spegnimento del sistema eseguendo i file eseguibili trovati nelle rispettive sottodirectory presenti nella loro directory home, denominati .startUp e .shutDown. Dato che non ho trovato nessun altro modo per farlo, ho scritto il mio script bash che fa esattamente questo e l'ho configurato come script di servizio (seguendo l'esempio di scheletro) in /etc/init.d/, quindi quando viene eseguito con l'argomento start lancia tutto dalle directory .startUp e quando viene eseguito con l'argomento stop avvia tutto dalle directory .shutDown di tutti gli utenti come loro.

In alternativa, sono anche interessato a utilizzare una soluzione esistente per risolvere questo problema.

AGGIORNAMENTO
Mi sono guardato un po 'in giro e ho trovato questa domanda: /unix/22478/detach-a-daemon-using-sudo

Risposta accettata lì, per usare:, sudo -u user sh -c "daemon & disown %1"funziona per me. Ma ho anche provato senza rinnegare% 1 ed è lo stesso. Quindi questo è ciò che funziona per me come mi aspettavo:

sudo -u <username> bash -c "<script_of_a_particular_user> &"

La mia domanda aggiuntiva ora è: perché funziona senza rinnegare? dovrei comunque lasciare la chiamata di disconoscimento , a prescindere, per qualche potenziale caso speciale?

AGGIORNAMENTO 2

Apparentemente funziona anche questo:

su <username> -c "<script_of_a_particular_user> &"

C'è qualche differenza tra questa chiamata e la chiamata sudo? So che questa è potenzialmente una domanda completamente diversa. Ma dal momento che sto trovando le risposte qui da solo forse per il bene di questo argomento qualcuno potrebbe chiarire questo qui.

AGGIORNAMENTO 3
Entrambi questi metodi con su o sudo ora producono un nuovo processo startpar (processo singolo che viene eseguito come root) dopo l'avvio della macchina. Visibile nell'elenco dei processi come:

startpar -f -- <name_of_my_init.d_script>

Perché viene generato questo processo? Ovviamente sto facendo qualcosa di sbagliato dal momento che nessun altro script init.d ha questo processo in esecuzione.

AGGIORNAMENTO 4
Il problema con startpar è stato risolto. Ho iniziato un'altra domanda per questo: il
processo startpar è rimasto sospeso all'avvio dei processi da rc.local o init.d

E un'altra domanda per discutere ulteriormente i meccanismi di lancio per utenti non privilegiati:
fornire agli utenti normali (non root) le funzionalità di inizializzazione e spegnimento automatico

Risposte:


18

La risposta corretta è stata che per una corretta "demonizzazione", l'input standard, l'output standard e l'errore standard devono essere reindirizzati a / dev / null (o qualche file reale):

su someuser -c "nohup some_script.sh >/dev/null 2>&1 &"

su - sostituisce l'identità dell'utente a someuser
-c - argomento su per eseguire il comando
nohup specificato - Esegue un comando immune agli hangup. Per evitare casi in cui il processo padre interromperà il processo figlio. Aggiunto qui per ogni evenienza. Ma in realtà non ha alcun effetto nel mio caso particolare. La necessità di dipendere dall'ambiente (controlla shopt )
> / dev / null - Reindirizza l'output standard su nulla, praticamente disabilitandolo.
2> & 1 - Reindirizza l'output dell'errore standard (2) sull'output standard (1), che viene reindirizzato su null
e - si stacca sullo sfondo, in questo modo reindirizzerà l'input standard anche su / dev / null.

Questo è essenzialmente esattamente ciò che l' utilità start-stop-daemon di Debian dpkg fa al suo interno. Ecco perché preferisco avviare gli script in questo modo piuttosto che introdurre un'altra chiamata di utilità esterna nel mio codice. start-stop-daemon è utile nei casi in cui si dispone di programmi daemon completi che è necessario avviare e in cui sono quindi necessarie funzionalità aggiuntive fornite da start-stop-daemon (ad esempio verificare se il processo specificato è già in esecuzione in modo che non non avviarlo di nuovo).

Vale anche la pena notare che puoi anche chiudere i descrittori di file del tuo processo invece di reindirizzarli a / dev / null , ad esempio:

su someuser -c "some_script.sh 0<&- 1>&- 2>&- &"

0 <& - Chiudi input standard (0)
1> & - Chiudi output standard (1)
2> & - Chiudi output errore standard (2)

La direzione dei segni <> non ha importanza poiché viene specificato il numero descrittore di file lungo. Quindi è altrettanto buono:

su someuser -c "some_script.sh 0>&- 1>&- 2>&- &"

o

su someuser -c "some_script.sh 0<&- 1<&- 2<&- &"

Tuttavia c'è un modo un po 'più breve per scrivere che, senza numeri per stdin e stdout, dove la direzione conta:

su someuser -c "some_script.sh <&- >&- 2>&- &" 

Quando i descrittori di file vengono chiusi o reindirizzati su / dev / null ( start-stop-daemon sta eseguendo il reindirizzamento su / dev / null), il processo può essere eseguito in background come daemon. Questo è ciò che è necessario per evitare problemi ( startpar ) con l'avvio di script durante l'avvio.

Ho implementato l'intera soluzione dalla mia idea iniziale e l'ho messa su GitHub:
https://github.com/ivankovacevic/userspaceServices


Ivan, è meglio usare su o su -login? Ho letto l'uomo di su ma non riesco a capire per questo caso specifico.
Massimo

1
@Massimo, scusami per il ritardo nella mia risposta! Dai un'occhiata a questa domanda: unix.stackexchange.com/questions/318572/… c'è una pagina di manuale migliore che lo spiega. Fondamentalmente la differenza è nell'impostazione della directory di lavoro e delle variabili di ambiente. Direi che per casi d'uso come questo (facendo qualcosa come un altro utente) potrebbe essere un'opzione preferibile per usare effettivamente -login
Ivan Kovacevic

3

È possibile utilizzare il demone start-stop di init.d con l' --useropzione.


Ho commentato start-stop-daemon sulla risposta di Mr Shark e ho anche fatto un aggiornamento alla mia risposta e alla mia domanda (aggiornamento 4)
Ivan Kovacevic,

2

Non l'ho ancora testato completamente, ma penso che qualcosa del tipo:

/sbin/start-stop-daemon --background --start --exec /home/USER/.startUp --user USER --pidfile=/home/USER/.startUp.pid --make-pidfile

all'avvio e poi

/sbin/start-stop-daemon --stop --user USER --pidfile=/home/USER/.startUp.pid

quando si spegne.

La gestione dello script .shutDown potrebbe essere eseguita da qualcosa come la cosa di avvio, ma non puoi essere sicuro che gli script vengano eseguiti fino alla fine poiché l'arresto dovrebbe avvenire comunque :-)

dovrebbe fare il trucco, forse dovresti lanciare un po 'di reindirizzamento dell'input, ma poi dovresti preoccuparti del riempimento dei file di registro.


2
In sostanza, questo avrebbe funzionato! start-stop-daemon può avviare correttamente i processi all'avvio o in altro modo. L'ho provato. E si sbarazza anche di quel problema con il processo di sospensione di startpar. Comunque manchi anche un UTENTE --chuid nella tua chiamata iniziale. Senza di essa, avvierebbe il processo come root. Il file pid dovrebbe anche essere probabilmente scritto in / var / run / poiché altrimenti genera un file di proprietà root nella home directory degli utenti. Ma, nella mia mente, per il lancio di script generici start-stop-daemon sembra essere un po 'eccessivo. Controlla la mia risposta dove ho cercato di elaborare il perché.
Ivan Kovacevic,

1

Hai provato a usare su?

su -c /home/user/.startUp/executable - user

-c dice a su di eseguire il comando e l'ultimo parametro è l'utente che lo esegue come.


sì, funziona ma con qualche citazione e aggiunta di e commerciale. E trovo più pulito scriverlo in questo modo: su <username> -c "/some/path/script.sh &" Fondamentalmente ho usato sudo poiché sembrava essere più pulito, ma ora sembra meglio che usare: sudo - u <nomeutente> bash -c "/some/path/script.sh &". Non so se ci siano differenze in quei due però
Ivan Kovacevic,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.