Perché "sudo su" in uno script di shell non esegue il resto dello script come root?


36

Uno script di esempio può essere il seguente:

#!/bin/bash
sudo su
ls /root

Quando si utilizza ./test.shcome utente normale, eseguire invece lscome superutente ed uscire, passa a root; e quando esco, viene eseguito ls /rootcome utente normale.

Qualcuno può parlarmi del meccanismo a riguardo?


13
sudo sumi fa male agli occhi.
Gelraen,

È usato perché le persone non conoscono abbastanza bene sudo e quindi hanno bisogno di un modo per eseguire su su sistemi in cui root è protetto da una password deliberatamente danneggiata. Sì, sudo "ridondifica" l'uso di su.
Johan

1
Non puoi semplicemente usare sudo -s, però?
Joe Z.

@Johan, lo uso spesso sudo superché sono più abituato alle opzioni di suquante ne sia di quelle di sudo. Conosco abbastanza bene le opzioni di sudo, ma posso digitarle più velocemente. Ma sì, credo che ciò significhi che non conosco abbastanza bene il sudo.
user606723

1
Ho appena controllato la pagina man sudo. Sembra sudo -isimile a su -mentre sudo -sfunziona come su(senza trattino)
Johan

Risposte:


49

I comandi in uno script vengono eseguiti uno per uno, indipendentemente. Lo script stesso come genitore di tutti i comandi nello script, è un altro processo indipendente e il comando su non lo fa e non può cambiarlo in root: il comando su crea un nuovo processo con i privilegi di root.

Al termine del comando su, il processo parent, sempre in esecuzione come lo stesso utente, eseguirà il resto dello script.

Quello che vuoi fare è scrivere uno script wrapper. I comandi con privilegi vanno nello script principale, ad esempio~/main.sh

#!/bin/sh
ls /root

Lo script wrapper chiama lo script principale con autorizzazioni di root, in questo modo

#!/bin/sh
su -c ~/main.sh root

Per avviare questo processo è necessario eseguire il wrapper, che a sua volta avvia lo script principale dopo il passaggio dell'utente all'utente root.

Questa tecnica wrapper può essere utilizzata per trasformare lo script in un wrapper attorno a se stesso. Fondamentalmente controlla se è in esecuzione come root, altrimenti usa "su" per riavviarlo.

$ 0 è un modo pratico per fare in modo che uno script faccia riferimento a se stesso e il comando whoami può dirci chi siamo (siamo root?)

Quindi diventa lo script principale con wrapper integrato

#!/bin/sh
[ `whoami` = root ] || exec su -c $0 root
ls /root

Nota l'uso di exec. Significa "sostituisci questo programma con", che termina effettivamente la sua esecuzione e avvia il nuovo programma, lanciato da su, con root, per essere eseguito dall'alto. L'istanza di sostituzione è "root", quindi non esegue il lato destro di ||


1
prima, un addendum a questo punto. Se stavo scrivendo una sceneggiatura simile farei solo un'istruzione if all'inizio che controlla $ EUID e se non è zero sudo stesso e esce, altrimenti continua con l'esecuzione della sceneggiatura.
Bratchley,

Accetto e aggiornerò la risposta per spiegare questo.
Johan

2
Forse è un po 'arcaico ma adoro i percorsi assoluti per ogni eseguibile, quindi qualcuno non può cambiare lo script ~ / main.sh in qualcosa di nefasto. Attacco alla parte USER della sceneggiatura
artifex

2
Potresti anche voler catturare gli argomenti che gli sono stati passati includendo un riferimento a $ *
Bratchley

@JoelDavis Mi imbatto sempre nel muro di "E se ci fossero spazi caratteri negli argomenti". Non ho mai trovato una soluzione soddisfacente. Una volta ho scritto uno script che ha messo i suoi argomenti in un file temporaneo, un argomento per riga, quindi ho chiamato tutto ciò di cui aveva bisogno e ho passato a quello script finale l'argomento di quale file leggere per trovare gli argomenti originali.
Johan

20

Utilizzare quanto segue nello script.

sudo su <<HERE
ls /root
HERE

Il codice tra il blocco HERE verrà eseguito come root.


6
sudo susta chiamando due programmi. Usa sudo -s <<HEREDOCo su user <<HEREDOC... Stupido limite di 5 minuti.
Johan

6

Senza ulteriori argomenti suverrà eseguita la shell di login per root. Ecco cosa fa effettivamente la prima riga della tua sceneggiatura. Quando si esce, si chiude la shell di login, ritorna su e inserire script continua l'esecuzione, che è con la seconda linea: ls /root. Penso che tu possa semplicemente sudo ls /rootfare quello che vuoi.


Sì, so di poterlo fare per ls, ma questo è solo un esempio. In effetti, devo fare molte più cose con il privilegio di root :-) Quindi preferisco la risposta di @ Ankit.
Hongxu Chen,

1

Una volta che si avvia sudo suun nuovo processo con l'effetto userid (euid=EUID)del super user biforcato, quindi abbiamo nuovi bash in esecuzione su ID processo diversi (pid=PID)associati allo stesso terminale (tname=TTY).

Spiegazione

Supponiamo che dopo aver sparato ps -A | grep bashtu abbia 21460 pts/2 00:00:00 bashcome output. Ora, quando esegui ./test.shentrambi i comandi sudo sue ls /rootverrai spoolizzato PID 21460. Dopo l'esecuzione quando rootl'utente viene ps -A | grep bashnuovamente colpito , noterai un nuovo bash in esecuzione PID say, 21570. L'uscita da root bashucciderà la bash appena biforcuta ripristinando user's bashe quindi esegue il comando di spooling ls /rootprima di rilasciare il prompt.


Se l'uso di su o sudo fosse "persistente" in bash (o in qualsiasi altro luogo) creerebbe molti più problemi di quanti ne risolva. È necessario fare il minimo possibile come root per sicurezza e protezione. Il punto principale di avere su e sudo (oltre alla sicurezza!) È farti riflettere attentamente su ciò che necessita dei privilegi di root.
Joe,
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.