Come spiegato da @geekosaur, la shell esegue il reindirizzamento prima di eseguire il comando. Quando digiti questo:
sudo foo >/some/file
Il tuo attuale processo di shell crea una copia di se stesso che prima prova ad aprirsi /some/file
per la scrittura, poi se ha successo, fa di quel descrittore di file il suo output standard e solo se ha successo lo esegue sudo
. Questo sta fallendo nel primo passaggio.
Se sei autorizzato (le configurazioni di sudoer spesso precludono l'esecuzione di shell), puoi fare qualcosa del genere:
sudo bash -c 'foo >/some/file'
Ma trovo che una buona soluzione in generale sia usare al | sudo tee
posto di >
e | sudo tee -a
invece di >>
. Ciò è particolarmente utile se il reindirizzamento è l'unico motivo di cui ho bisogno sudo
in primo luogo; dopotutto, eseguire inutilmente processi come root è esattamente ciò che è sudo
stato creato per evitare. E correre echo
come root è semplicemente stupido.
echo '[archlinuxfr]' | sudo tee -a /etc/pacman.conf >/dev/null
echo 'Server = http://repo.archlinux.fr/$arch' | sudo tee -a /etc/pacman.conf >/dev/null
echo ' ' | sudo tee -a /etc/pacman.conf >/dev/null
Ho aggiunto > /dev/null
alla fine perché tee
invia il suo output sia al file denominato che al proprio output standard, e non ho bisogno di vederlo sul mio terminale. (Il tee
comando si comporta come un connettore a "T" in una pipeline fisica, da cui prende il nome.) E sono passato alle virgolette singole ( '
... '
) invece delle doppie ( "
... "
) in modo che tutto sia letterale e io non è stato necessario inserire una barra rovesciata davanti a $
in $arch
. (Senza le virgolette o la barra rovesciata, $arch
verrebbe sostituito dal valore del parametro della shell arch
, che probabilmente non esiste, nel qual caso $arch
viene sostituito da niente e svanisce.)
Quindi questo si occupa di scrivere sui file come root usando sudo
. Ora per una lunga digressione sui modi per produrre testo contenente una nuova riga in uno script di shell. :)
Per BLUF, come si suol dire, la mia soluzione preferita sarebbe semplicemente inserire un here-document nel sudo tee
comando precedente ; quindi non c'è bisogno di cat
or echo
or printf
o altri comandi. Le virgolette singole sono state spostate nell'introduzione della sentinella <<'EOF'
, ma lì hanno lo stesso effetto: il corpo viene trattato come testo letterale, quindi $arch
viene lasciato solo:
sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[archlinuxfr]
Server = http://repo.archlinux.fr/$arch
EOF
Ma mentre è così che lo farei, ci sono alternative. Eccone alcuni:
Puoi restare con uno echo
per riga, ma raggruppali tutti insieme in una subshell, quindi devi solo aggiungerli al file una volta:
(echo '[archlinuxfr]'
echo 'Server = http://repo.archlinux.fr/$arch'
echo ' ') | sudo tee -a /etc/pacman.conf >/dev/null
Se aggiungi -e
a echo
(e stai usando una shell che supporta quell'estensione non POSIX), puoi incorporare newline direttamente nella stringa usando \n
:
echo -e '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Ma come si dice sopra, questo non è un comportamento specificato da POSIX; la tua shell potrebbe semplicemente echeggiare un letterale -e
seguito da una stringa con un mucchio di \n
s letterali . Il modo POSIX per farlo è usare printf
invece di echo
; tratta automaticamente il suo argomento come echo -e
fa, ma non aggiunge automaticamente una nuova riga alla fine, quindi devi aggiungere un extra anche \n
lì:
printf '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n \n' |
sudo tee -a /etc/pacman.conf >/dev/null
Con una di queste soluzioni, ciò che il comando ottiene come stringa di argomento contiene la sequenza di due caratteri \n
e spetta al programma di comando stesso (il codice all'interno di printf
o echo
) tradurlo in una nuova riga. In molte shell moderne, hai la possibilità di utilizzare virgolette ANSI $'
... '
, che tradurranno sequenze come \n
in lettere a capo prima che il programma di comando veda la stringa. Ciò significa che tali stringhe funzionano con qualsiasi comando, incluso il semplice old -e
-less echo
:
echo $'[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Ma, sebbene più portabili di echo -e
, le virgolette ANSI sono ancora un'estensione non POSIX.
E ancora, sebbene quelle siano tutte opzioni, preferisco la tee <<EOF
soluzione diretta sopra.