bash: / dev / stderr: autorizzazione negata


19

Dopo l'aggiornamento a una nuova versione di rilascio, i miei bashscript iniziano a sputare errori:

bash: /dev/stderr: Permission denied

nelle versioni precedenti Bash avrebbe riconosciuto internamente quei nomi di file (motivo per cui questa domanda non è un duplicato di questo ) e farebbe la cosa giusta (tm) , tuttavia, ora ha smesso di funzionare. Cosa posso fare per poter eseguire nuovamente i miei script correttamente?

Ho provato ad aggiungere l'utente che esegue lo script al gruppo tty, ma questo non fa differenza (anche dopo aver effettuato il logout e il back in).

Posso riprodurlo dalla riga di comando senza problemi:

$ echo test > /dev/stdout
bash: /dev/stdout: Permission denied
$ echo test > /dev/stderr
bash: /dev/stderr: Permission denied
$ ls -l /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stdout -> /proc/self/fd/1
$ ls -lL /dev/stdout /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stdout
$ echo $BASH_VERSION
4.2.24(1)-release

Su un sistema precedente (Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release

1
Qual è l'output di ls -l /dev/stdout /dev/stderre ls -lL /dev/stdout /dev/stderr?
— Keith Thompson,

@Keith: vedi la mia domanda modificata. Ciò significa che Bash ha completamente abbandonato la gestione interna di questo? Sui sistemi più vecchi questi collegamenti simbolici non esistevano e tuttavia il codice funzionava senza problemi. Si noti, questo viene eseguito impersonato tramite sudo su username2 -...
— 0xC0000022L

Quale versione bash stai usando? echo $BASH_VERSION
— jippie,

1
Quali sono le versioni vecchie e nuove (prima e dopo del tuo sistema operativo e di bash?
— Keith Thompson,

Risposte:


41

Non penso che questo sia interamente un problema bash.

In un commento, hai detto di aver visto questo errore dopo averlo fatto

sudo su username2

quando si accede come username. È il sufattore scatenante del problema.

/dev/stdoutè un link simbolico a /proc/self/fd/1, che è un link simbolico, ad esempio, /dev/pts/1. /dev/pts/1, che è uno pseudoterminale, è di proprietà di e scrivibile da username; tale proprietà è stata concessa al momento dell'accesso username. Quando tu sudo su username2, la proprietà di /dev/pts/1non cambia e username2non hai il permesso di scrivere.

Direi che questo è un bug. /dev/stdout dovrebbe essere, in effetti, un alias per il flusso di output standard, ma qui vediamo una situazione in cui echo hellofunziona ma echo hello > /dev/stdoutfallisce.

Una soluzione alternativa sarebbe quella di creare username2un membro del gruppo tty, ma ciò darebbe il username2permesso di scrivere a qualsiasi tty, il che è probabilmente indesiderabile.

Un'altra soluzione alternativa sarebbe quella di accedere username2all'account anziché utilizzare su, in modo che /dev/stdoutpunti a uno pseudoterminale appena assegnato di proprietà username2. Questo potrebbe non essere pratico.

Un'altra soluzione alternativa sarebbe quella di modificare i tuoi script in modo che non facciano riferimento a /dev/stdoute /dev/stderr; ad esempio, sostituire questo:

echo OUT > /dev/stdout
echo ERR > /dev/stderr

da questo:

echo OUT
echo ERR 1>&2

Vedo questo sul mio sistema, Ubuntu 12.04, con bash 4.2.24 - anche se il documento bash ( info bash) sul mio sistema lo dice /dev/stdoute /dev/stderrsono trattati specialmente quando usati nei reindirizzamenti. Ma anche se bash non tratta questi nomi in modo particolare, dovrebbero comunque fungere da equivalenti per i flussi I / O standard. (POSIX non menziona /dev/std{in,out,err}, quindi potrebbe essere difficile sostenere che si tratta di un bug.)

Osservando le vecchie versioni di bash, la documentazione implica che /dev/stdoutet al sia trattato in modo speciale indipendentemente dal fatto che i file esistano o meno. La funzionalità è stata introdotta in bash 2.04 e il NEWSfile per quella versione dice:

Il codice di reindirizzamento ora gestisce diversi nomi di file appositamente: / dev / fd / N, / dev / stdin, / dev / stdout e / dev / stderr, indipendentemente dal fatto che siano presenti nel file system.

Ma se si esamina il codice sorgente ( redir.c), si vedrà che la gestione speciale è abilitata solo se il simbolo HAVE_DEV_STDINè definito (questo è determinato quando bash è costruito dal sorgente).

Per quanto ne so, nessuna versione rilasciata di bash ha reso /dev/stdoutincondizionata la gestione speciale di et al - a meno che qualche distribuzione non l'abbia corretto.

Quindi un'altra soluzione alternativa (che non ho provato) sarebbe quella di afferrare i sorgenti di bash , modificarli redir.cper rendere /dev/*incondizionata la gestione speciale e usare la tua versione ricostruita piuttosto che quella fornita con il tuo sistema. Questo è probabilmente eccessivo, però.

SOMMARIO :

Il tuo sistema operativo, come il mio, non gestisce la proprietà e le autorizzazioni di /dev/stdoute /dev/stderrcorrettamente. bash presumibilmente tratta questi nomi specialmente nei reindirizzamenti, ma in realtà lo fa solo se i file non esistono. Questo non sarebbe un problema se /dev/stdoute /dev/stderrfunzionava correttamente. Questo problema si presenta solo quando si suaccede a un altro account o si fa qualcosa di simile; se accedi semplicemente a un account, le autorizzazioni sono corrette.


La proprietà del TTY dovrebbe cambiare. Questo è ciò che ConsoleKit (aka pam_ck_connector.soè per).
— Mikel,

In realtà, potrei sbagliarmi. Dovrà scavare di più.
— Mikel,

Sui miei sistemi, /proc/self/fd/1sta aggiornando le sue autorizzazioni, ma è inutile, dal momento che è un collegamento simbolico. Succede anche su Fedora, che sembra escludere ConsoleKit.
— Mikel,

1

In realtà la ragione di ciò è che udev imposta specificatamente le autorizzazioni su 0620 su dispositivi tty e su non modifica né la proprietà né le autorizzazioni né dovrebbe. A mio avviso, ciò ci lascia in una situazione che rende / dev / std * non portatile.

La soluzione semplice è quella di mettere "mesg y" in / etc / profile (o qualunque profilo di primo livello che ti piace usare) poiché questo cambia le autorizzazioni del tuo dispositivo tty a 0622. Non mi piace molto, ma probabilmente è meglio che cambiare le regole di udev.


"msg y" non funziona
— Luciano,

Aspetta ... forse la ricerca di Bash gestisce diversi nomi di file specialmente quando vengono utilizzati nei reindirizzamenti nella pagina man di Bash.
— 0xC0000022L

0

Come utente Linux da molto tempo ho recentemente installato un nuovo sistema Ubuntu a 64 bit 12.04 LTS ed ero sconcertato dal motivo per cui i miei script bash non funzionavano - permesso negato - e successivamente ho trovato questo thread. Ho pensato che il problema potrebbe essere dovuto a qualcosa nel nuovo sistema operativo.

Alla fine si è scoperto che avevo stupidamente usato uno strumento UI per impostare le autorizzazioni sulla mia /homedirectory e il problema era correlato all'unità . A dire il vero, ho creato una tempdirectory /opte ho scoperto che i miei script avrebbero funzionato bene da lì. Una volta riparate le /homeautorizzazioni del drive, tutto era tornato alla normalità.

Un piccolo mistero risolto. sospiro


2
Questo deve essere stato un errore diverso. La modifica di qualcosa in / home non influisce su / dev.
— ott--

-1

Questa è una vecchia domanda, ma penso che sia ancora molto rilevante, quindi ecco la soluzione che ho trovato che non è menzionata qui.

Mi sono imbattuto in questa domanda poiché ho anche riscontrato problemi in un comando 'su' che eseguiva un comando come questo in bash:

echo test > /dev/stderr

Dal momento che tutto ciò che sto cercando di fare è reindirizzare stdout su stderr, quanto segue ottiene lo stesso, e funziona anche con l'account 'su' commutato:

echo test 1>&2
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.