Hay una pregunta similar que trata con el escenario de 'envoltura', donde desea reemplazar, por ejemplo, cd
con un comando que llama al incorporado cd
.
Sin embargo, a la luz de shellshock et al y sabiendo que bash importa funciones del entorno, he realizado algunas pruebas y no puedo encontrar una manera segura de llamar al builtin cd
desde mi script.
Considera esto
cd() { echo "muahaha"; }
export -f cd
Cualquier script llamado en este entorno usando cd
se romperá (considere los efectos de algo así cd dir && rm -rf .
).
Hay comandos para verificar el tipo de comando (convenientemente llamado type
) y comandos para ejecutar la versión incorporada en lugar de una función ( builtin
y command
). Pero, he aquí, estos pueden ser anulados usando funciones también
builtin() { "$@"; }
command() { "$@"; }
type() { echo "$1 is a shell builtin"; }
Producirá lo siguiente:
$ type cd
cd is a shell builtin
$ cd x
muahaha
$ builtin cd x
muahaha
$ command cd x
muahaha
¿Hay alguna manera de forzar a bash de manera segura a usar el comando incorporado, o al menos detectar que un comando no es un incorporado, sin borrar todo el entorno?
Me doy cuenta de que si alguien controla su entorno, probablemente esté jodido de todos modos, pero al menos para los alias tiene la opción de no llamar al alias insertando un \
antes.
env
comando antes, como este:env -i <SCRIPT.sh>
env
no se redefine como una función también. Esto es aterrador Primero pensé que los caracteres especiales ayudarían: llamar con la ruta completa que incluye/
, usar.
a la fuente, etc. ¡Pero esos también se pueden usar para nombres de funciones! Usted puede redefinir cualquier función que desee, pero es difícil volver a llamar al mandato original.#/bin/sh
si este no es un shell interactivo predeterminado.Respuestas:
Olivier D es casi correcto, pero debe configurarlo
POSIXLY_CORRECT=1
antes de ejecutarlounset
. POSIX tiene una noción de Special Built-ins , y bash lo admite .unset
es uno de esos incorporados. BuscarSPECIAL_BUILTIN
enbuiltins/*.c
la fuente de fiesta para una lista, que incluyeset
,unset
,export
,eval
ysource
.El pícaro
unset
ahora ha sido retirado del medio ambiente, si de borracommand
,type
,builtin
entonces usted debería ser capaz de proceder, perounset POSIXLY_CORRECT
si usted está confiando en un comportamiento no POSIX o características de bash avanzadas.Sin embargo, esto no aborda los alias, por lo que debe usar
\unset
para asegurarse de que funciona en un shell interactivo (o siempre, en caso de queexpand_aliases
esté vigente).Para los paranoicos, esto debería arreglarlo todo, creo:
(
while
,do
,done
Y[[
son palabras reservadas y no necesitan precauciones.) Tenga en cuenta que estamos utilizandounset -f
para asegurarse de que las funciones no definidas, aunque variables y funciones comparten el mismo espacio de nombres que es posible tanto para existir simultáneamente (gracias a Etan Reisner), en cuyo caso Inmovilizar dos veces también haría el truco. Usted puede marcar una función de sólo lectura, golpe del no impide que desarmar una función de sólo lectura hasta e incluyendo bash-4.2, bash-4.3 le impide pero todavía rinde homenaje a las órdenes internas especiales cuandoPOSIXLY_CORRECT
se establece.Un solo lectura
POSIXLY_CORRECT
no es un problema real, no es un booleano o marca su presencia habilita el modo POSIX, por lo que si existe como solo lectura puede confiar en las características POSIX, incluso si el valor está vacío o 0. Simplemente necesitará desarma las funciones problemáticas de una manera diferente a la anterior, quizás con algo de cortar y pegar:(e ignorar cualquier error) o participar en otros scriptobatics .
Otras notas:
function
es una palabra reservada, puede ser alias pero no anulada con una función. (El aliasfunction
es levemente problemático porque\function
no es aceptable como una forma de evitarlo)[[
,]]
son palabras reservadas, pueden tener un alias (que será ignorado) pero no anularse con una función (aunque las funciones pueden llamarse así)((
no es un nombre válido para una función, ni un aliasfuente
unset
se sobrescriba.-f
argumento paraunset
no? De lo contrario, si se definen una variable y una función con el mismo nombre que una función incorporada,unset
primero se seleccionará la variable para desarmar. También esto falla si alguna de las funciones oscurecedoras está configurada,readonly
¿no? (Aunque eso es detectable y se puede cometer un error fatal). También[
parece que esto falla .\unset -f unset
tenga sentido, dado que se hará en el ciclo de lectura. Siunset
es una función\unset
que normalmente resolvería en lugar de la integrada, pero puede usarla con\unset
seguridad siempre que el modo POSIX esté vigente. Explícitamente llamar\unset -f
en[
,.
y:
podría ser una buena idea, aunque, como sus expresiones regulares excluye ellos. También agregaría-f
al\unset
en el bucle, y lo haría\unset POSIXLY_CORRECT
después del bucle, en lugar de antes.\unalias -a
(after\unset -f unalias
) también le permite a uno renunciar de manera segura al escape en los comandos posteriores.[[ ${POSIXLY_CORRECT?non-POSIX mode shell is untrusted}x ]]
esto provocará que una secuencia de comandos no interactiva salga con el error indicado si la variable no está configurada o continúe si está configurada (vacía o cualquier valor).\unset
" ... Debe tenerse en cuenta que la cita de cualquier carácter funcionaría para evitar la expansión del alias, no solo el primero.un"se"t
funcionaría igual de bien, pero menos legible. "La primera palabra de cada comando simple, si no se cita, se verifica para ver si tiene un alias". - Bash RefSi, eso. Si ejecuta un script en un entorno desconocido, todo tipo de cosas pueden salir mal, comenzando por
LD_PRELOAD
hacer que el proceso de shell ejecute código arbitrario antes de que incluso lea su script. Intentar protegerse contra un entorno hostil desde el interior del script es inútil.Sudo ha estado desinfectando el medio ambiente eliminando todo lo que parece una definición de función bash durante más de una década. Desde Shellshock , otros entornos que ejecutan script de shell en un entorno no totalmente confiable han seguido su ejemplo.
No puede ejecutar de forma segura un script en un entorno que haya sido configurado por una entidad no confiable. Por lo tanto, preocuparse por las definiciones de funciones no es productivo. Desinfecte su entorno y, al hacerlo, las variables que bash interpretarían como definiciones de funciones.
fuente
/bin/cat
a un chroot podría estar llamando a cualquier cosa). Desinfectar el medio ambiente te da unaPATH
razón (suponiendo que lo estás haciendo bien, por supuesto). Todavía no entiendo tu punto.Puede usar
unset -f
para eliminar las funciones incorporadas, comando y tipo.fuente
unset() { true; }
se encarga de eso.