GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cuál es la forma más segura y portátil de invocar el binario de eco?

Tenga en cuenta que coreutils es un paquete de software desarrollado por el proyecto GNU para proporcionar un conjunto de utilidades básicas de Unix a los sistemas GNU. Solo encontrarás coreutils echo listo para usar en sistemas GNU (Debian , trisquel , Cygwin , Fedora , CentOS ...). En otros sistemas, encontrará un diferente (generalmente con un comportamiento diferente como echo es una de las aplicaciones menos portátiles) implementación. FreeBSD tendrá FreeBSD echo , la mayoría de los sistemas basados ​​en Linux tendrán busybox echo , AIX tendrá AIX echo ...

Algunos sistemas incluso tendrán más de uno (como /bin/echo y /usr/ucb/echo en Solaris (este último forma parte del paquete que ahora es opcional en versiones posteriores de Solaris, como el paquete de utilidades para GNU del que obtendría un /usr/gnu/bin/echo ) todos con CLI diferentes).

GNU coreutils ha sido portado a la mayoría de los sistemas similares a Unix (e incluso a los que no son similares a Unix, como MS Windows), por lo que podría compilar coreutils ' echo en la mayoría de los sistemas, pero probablemente no sea eso lo que está buscando.

También tenga en cuenta que encontrará incompatibilidades entre las versiones de coreutils echo (por ejemplo, solía no reconocer \x41 secuencias con -e ) y que su comportamiento puede verse afectado por el entorno (POSIXLY_CORRECT variables).

Ahora, para ejecutar el echo del sistema de archivos (encontrado mediante una búsqueda de $PATH ), como para cualquier otra función integrada, la forma típica es con env :

env echo this is not the builtin echo

En zsh (cuando no esté emulando otros shells), también puede hacer:

command echo ...

sin tener que ejecutar un env extra comando.

Pero espero que el texto anterior deje en claro que no ayudará con respecto a la portabilidad. Para portabilidad y confiabilidad, use printf en su lugar.


# $(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'

Creo que esta es una mala idea, para ser honesto, pero hará un trabajo bastante sólido al encontrar el coreutils echo en un ambiente razonable. Esos son comandos compatibles con POSIX de principio a fin (getconf , find , sh , grep , strings , printf , head ), por lo que debería comportarse igual en todas partes. El getconf nos da las versiones compatibles con POSIX de cada una de esas herramientas primero en la ruta, en los casos en que las versiones predeterminadas no son estándar.

Encuentra cualquier ejecutable que contenga cadenas imprimibles "GNU coreutils" y "Echo the STRING(s) to standard output", que aparecen en el GNU echo de --help salida y están literalmente en el texto del programa. Si hay más de una copia, elige arbitrariamente la primera que encuentra. Si no se encuentra ninguno, falla:el $(...) se expande a una cadena vacía.

Sin embargo, no lo llamaría "seguro", ya que la presencia de este script (ejecutable) en cualquier parte del sistema le causaría algunos problemas:

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

Entonces, para reiterar, creo que esta es una muy mala idea. A menos que vaya a incluir hashes en la lista blanca de echo conocidos s, no existe una forma razonable y portátil de encontrar una versión determinada que sea segura para ejecutarse en sistemas desconocidos. En algún momento tendrás que ejecutar algo basado en una conjetura.

Te animo a usar el printf en su lugar, que acepta un formato y cualquier argumento que desee usar literalmente.

# printf '%s' -e
-e

printf está en POSIX y debería comportarse de la misma manera para todos los sistemas si proporciona un formato.


Personalmente, evito echo completamente en mis scripts de shell y uso printf '%s\n' blablabla cuando la cadena es corta y documento aquí cuando la cadena es larga.

Citando de §11.14 Limitaciones de Shell Builtins del manual de autoconf:

eco

El sencillo echo es probablemente la fuente más sorprendente de problemas de portabilidad. No es posible usar echo portable a menos que se omitan tanto las opciones como las secuencias de escape. No esperes ninguna opción.

No use barras invertidas en los argumentos, ya que no hay consenso sobre su manejo. Para echo '\n' | wc -l , el sh de Solaris salidas 2 , pero Bash y Zsh (en sh modo de emulación) salida 1 . El problema es realmente echo :todos los proyectiles entienden '\n' como la cadena compuesta por una barra invertida y un n . Dentro de una sustitución de comando, echo 'string\c' estropeará el estado interno de ksh88 en AIX 6.1 para que imprima el primer carácter s solo, seguido de una nueva línea, y luego descartar por completo la salida del siguiente eco en una sustitución de comando.

Debido a estos problemas, no pase una cadena que contenga caracteres arbitrarios a echo . Por ejemplo, echo "$foo" es seguro solo si sabes que foo El valor de no puede contener barras invertidas y no puede comenzar con - .

Si esto no es cierto, printf es en general más seguro y fácil de usar que echo y echo -n . Por lo tanto, los scripts en los que la portabilidad no es una preocupación importante deben usar printf '%s\n' siempre que echo podría fallar, y de manera similar use printf %s en lugar de echo -n . En cambio, para scripts de shell portátiles, se sugiere usar un documento aquí como este:

          cat <<EOF
          $foo
          EOF

Linux
  1. ¿Cuál es la forma más segura de obtener privilegios de raíz:Sudo, Su o iniciar sesión?

  2. Copia de seguridad en la nube frente a copia de seguridad local:la forma más segura de almacenar datos

  3. ¿Cuál es la forma más sencilla de SSH usando Python?

  4. ¿Cuál es la forma correcta de instalar jdk en Linux?

  5. ¿Cuál es el uso de $# en Bash?

¿Cuál es la forma correcta de usar inotify?

¿Cuál es la forma correcta de insertar una pestaña en sed?

¿Cuál es la forma más fácil de liberar espacio en un disco duro?

¿Cuál es la mejor manera de aprender SELinux?

¿Cuál es la forma más rápida de ejecutar un script?

¿Cuál es la forma más segura de permitir que un usuario tenga acceso de lectura a un archivo de registro?