GNU/Linux >> Linux Esercitazione >  >> Linux

Perché il documento Parent Shell Here non funziona per il sottocomando in Dash ma Bash funziona?

Sono eseguito su debian stretch, tutti sotto i comandi (dash e bash ) viene inserito in bash.
Il whoami sembra non essere mai eseguito come test dell'utente in trattino come nei codici sottostanti.

$ sudo dash << 'end'
> su test
> whoami
> end
root
$ sudo bash << 'end'
> su test
> whoami
> end
test

Risposta accettata:

Considera invece questo esempio:

$ cat f
grep pos /proc/self/fdinfo/0
IFS= read -r var
echo A
echo B
printf '%s\n' "var=$var"
$ bash < f
pos:    29
B
var=echo A
$ dash < f
pos:    85
A
B
var=

Come puoi vedere, al momento il grep viene eseguito, la posizione all'interno di stdin è alla fine del file con dash , e subito dopo la nuova riga che segue grep comando in bash .

Il echo A il comando è eseguito da dash ma nel caso di bash , viene alimentato come input per read .

Quello che è successo è quel dash leggi l'intero input (in realtà, un blocco di testo) mentre bash leggere una riga alla volta prima di eseguire i comandi.

Per farlo, bash dovrebbe leggere un byte alla volta per assicurarsi che non legga oltre la nuova riga, ma quando l'input è un file normale (come nel caso del mio f file sopra, ma anche per here-documenti che bash implementa come file temporanei, mentre dash utilizza pipe), bash lo ottimizza leggendo per blocchi e tornando alla fine della riga, che puoi vedere con strace su Linux:

$ strace -e read,lseek bash < f
[...]
lseek(0, 0, SEEK_CUR)                   = 0
read(0, "grep pos /proc/self/fdinfo/0\nIFS"..., 85) = 85
lseek(0, -56, SEEK_CUR)                 = 29
pos:    29
[...]

$ strace -e read,lseek dash < f
read(0, "grep pos /proc/self/fdinfo/0\nIFS"..., 8192) = 85
pos:    85
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12422, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
read(0, "", 1)                          = 0
[...]

Quando stdin è un dispositivo terminale, ogni read() restituisce le righe come inviate dal terminale, quindi generalmente vedi un comportamento simile in bash e dash .

Nel tuo caso potresti fare:

sudo dash << 'end-of-script'
su test <<"end"
whoami
end
end-of-script

o meglio:

sudo sh -c '
  su test -c whoami
'

o meglio ancora:

sudo -u test whoami

Linux
  1. Personalizzazione della shell Bash

  2. Perché l'espressione regolare funziona in X ma non in Y?

  3. Perché il ~/.bash_profile non funziona?

  4. Perché il Pgid dei processi figlio non è il Pid del genitore?

  5. Perché la sostituzione del processo Bash non funziona con alcuni comandi?

Perché il file di traduzione Bash non contiene tutti i testi di errore?

Linux:perché Locale Es_mx funziona ma non Es?

Perché questo "durante la lettura" funziona in un terminale, ma non in uno script di shell?

Perché la Regex in Bash funziona solo se è una variabile e non direttamente??

Perché 'dd' non funziona per la creazione di USB avviabile?

Perché SUID è disabilitato per gli script di shell ma non per i file binari?