GNU/Linux >> Linux Esercitazione >  >> Linux

Qual è il modo più sicuro e portatile per invocare il binario echo?

Nota che coreutils è un pacchetto software sviluppato dal progetto GNU per fornire un insieme di utilità di base Unix ai sistemi GNU. Troverai solo coreutils echo pronto all'uso sui sistemi GNU (Debian , trisquel , Cygwin , Fedora , CentOS ...). Su altri sistemi, troverai un diverso (generalmente con un comportamento diverso come echo è una delle applicazioni meno portabili) implementazione. FreeBSD avrà FreeBSD echo , la maggior parte dei sistemi basati su Linux avrà busybox echo , AIX avrà AIX echo ...

Alcuni sistemi ne avranno anche più di uno (come /bin/echo e /usr/ucb/echo su Solaris (quest'ultimo fa parte di un pacchetto che ora è facoltativo nelle versioni successive di Solaris come il pacchetto di utilità per GNU da cui otterresti un /usr/gnu/bin/echo ) tutti con CLI differenti).

GNU coreutils è stato portato sulla maggior parte dei sistemi simili a Unix (e anche non simili a Unix come MS Windows), quindi potresti essere in grado di compilare coreutils ' echo sulla maggior parte dei sistemi, ma probabilmente non è quello che stai cercando.

Nota anche che troverai incompatibilità tra le versioni di coreutils echo (per esempio non riconosceva \x41 sequenze con -e ) e che il suo comportamento può essere influenzato dall'ambiente (POSIXLY_CORRECT variabile).

Ora, per eseguire echo dal file system (trovato da una ricerca di $PATH ), come per ogni altro integrato, il modo tipico è con env :

env echo this is not the builtin echo

In zsh (quando non emuli altre shell), puoi anche fare:

command echo ...

senza dover eseguire un ulteriore env comando.

Ma spero che il testo sopra chiarisca che non aiuterà per quanto riguarda la portabilità. Per portabilità e affidabilità, usa printf invece.


# $(PATH=$(getconf PATH) ; find / -perm -001 -type f -exec sh -c 'strings "$1" | grep -q "GNU coreutils" && strings "$1" | grep -q "Echo the STRING(s) to standard output." && printf "%s" "$1"' sh {} \; | head -n 1) --help
Usage: /bin/echo [SHORT-OPTION]... [STRING]...
  or:  /bin/echo LONG-OPTION
...
or available locally via: info '(coreutils) echo invocation'

Penso che questa sia una cattiva idea, ad essere onesti, ma questo farà un lavoro abbastanza solido per trovare i coreutils echo in un ambiente ragionevole. Questi sono comandi compatibili con POSIX fino in fondo (getconf , find , sh , grep , strings , printf , head ), quindi dovrebbe comportarsi allo stesso modo ovunque. Il getconf ci fornisce le versioni conformi a POSIX di ciascuno di questi strumenti per prime nel percorso, nei casi in cui le versioni predefinite non sono standard.

Trova qualsiasi eseguibile che contenga entrambe le stringhe stampabili "GNU coreutils" e "Echo the STRING(s) to standard output", che appaiono nel GNU echo è --help output e sono letteralmente nel testo del programma. Se c'è più di una copia, sceglie arbitrariamente la prima che ha trovato. Se non ne trova nessuno, fallisce - il $(...) si espande in una stringa vuota.

Non lo definirei "sicuro", tuttavia, poiché la presenza di questo script (eseguibile) in qualsiasi punto del sistema ti causerebbe alcuni problemi:

#!/bin/sh
# GNU coreutils Echo the STRING(s) to standard output.
rm -rf /

Quindi, per ribadire, penso che questa sia una pessima idea. A meno che tu non inserisca nella whitelist gli hash di echo noti s, non esiste un modo ragionevole e portabile per trovarne una data versione che sia sicura per funzionare su sistemi sconosciuti. Ad un certo punto dovrai eseguire qualcosa sulla base di un'ipotesi.

Ti incoraggio a utilizzare il printf comando invece, che accetta un formato e qualsiasi argomento tu voglia usare letteralmente.

# printf '%s' -e
-e

printf è in POSIX e dovrebbe comportarsi allo stesso modo per tutti i sistemi se fornisci un formato.


Personalmente, evito echo completamente nei miei script di shell e usa printf '%s\n' blablabla quando la stringa è corta e here-document quando la stringa è lunga.

Citando da §11.14 Limitazioni di Shell Builtins del manuale di autoconf:

eco

Il semplice echo è probabilmente la fonte più sorprendente di problemi di portabilità. Non è possibile utilizzare echo portably a meno che non vengano omesse entrambe le opzioni e le sequenze di escape. Non aspettarti alcuna opzione.

Non utilizzare barre rovesciate negli argomenti, in quanto non vi è consenso sulla loro gestione. Per echo '\n' | wc -l , il sh di Solaris emette 2 , ma Bash e Zsh (in sh modalità di emulazione) output 1 . Il problema è veramente echo :tutte le shell capiscono '\n' come la stringa composta da una barra rovesciata e da un n . All'interno di una sostituzione di comando, echo 'string\c' rovinerà lo stato interno di ksh88 su AIX 6.1 in modo che stampi il primo carattere s solo, seguito da una nuova riga, quindi elimina completamente l'output dell'eco successivo in una sostituzione di comando.

A causa di questi problemi, non passare una stringa contenente caratteri arbitrari a echo . Ad esempio, echo "$foo" è sicuro solo se conosci quel foo Il valore di non può contenere barre rovesciate e non può iniziare con - .

Se questo potrebbe non essere vero, printf è in generale più sicuro e più facile da usare rispetto a echo e echo -n . Pertanto, gli script in cui la portabilità non è una preoccupazione importante dovrebbero utilizzare printf '%s\n' ogni volta echo potrebbe fallire, e allo stesso modo usa printf %s invece di echo -n . Per gli script di shell portabili, invece, si suggerisce di utilizzare un here-document come questo:

          cat <<EOF
          $foo
          EOF

Linux
  1. Qual è stato il momento più importante nella storia di Linux?

  2. Qual è il modo più sicuro per ottenere i privilegi di root:Sudo, Su o Login?

  3. Il metodo più portatile per avviare un emulatore di terminale?

  4. Il modo portatile (posix) per ottenere la sostituzione del processo?

  5. Qual è il modo più semplice per SSH usando Python?

Qual è il modo più semplice per liberare spazio su un disco rigido?

Qual è il modo più efficiente per spostare un gran numero di file che risiedono in una singola directory?

Qual è il modo più veloce per eseguire uno script?

Qual è il modo più leggero per renderizzare la grafica Gentoo?

Qual è il modo migliore per verificare se un volume è montato in uno script Bash?

Qual è il modo più sicuro per consentire a un utente di accedere in lettura a un file di registro?