¿Cuál es la forma más adecuada de distribuir los scripts de shell si los comportamientos de los shells pueden modificarse set
y, por lo tanto, son impredecibles?
Por ejemplo, rm *.txt
no se ejecutaría como se esperaba en los entornos en los que set -f
se ha ejecutado. ¿Cómo debo asegurarme de que rm *.txt
elimine todos los archivos de texto en un directorio actual en cualquier entorno?
¿Cómo debo asegurarme de que los scripts de shell se ejecutarán como se esperaba antes de distribuirlos en general?
bash
shell
shell-script
hoge
fuente
fuente
shell_state=$(set +o)
... guión ...eval "$shell_state"
#!
para especificar qué opciones de shell desea.Respuestas:
Los scripts de shell normalmente se tratan como si fueran los mismos que cualquier otro tipo de archivo ejecutable, como archivos binarios, scripts de Python, scripts de Perl o cualquier otro tipo de script. Tienen un shebang en la parte superior que dirige el núcleo para ejecutarlos a través del shell. Se espera que se invoquen de la misma manera que cualquier otro comando.
Como tal, se inicia un nuevo shell cada vez que se invoca el script, y cualquier configuración como la
set -f
presente en el shell de invocación o en cualquier otra instancia de shell en el sistema es irrelevante.Por supuesto, es posible que los usuarios obtengan su script en lugar de ejecutarlo, por ejemplo, así:
o para ejecutarlo en un shell que tiene configuraciones no predeterminadas como esta:
pero esas no se consideran formas normales o invocando su script, y los usuarios que hacen eso deben esperar lo que obtengan como resultado.
Tenga en cuenta que hay algunos scripts que están destinados a ser obtenidos, no ejecutados, porque su propósito es hacer cosas como cambiar el cwd o establecer variables de entorno que deben reflejarse en el entorno del shell de abastecimiento, pero son minoritarias y generalmente se hace como parte de un protocolo acordado. Estos archivos se pueden considerar más como "complementos" para cualquier sistema del que esperan obtener, no tanto como scripts independientes. Por ejemplo, los archivos
/etc/rc*.d
con nombres que terminan.sh
provienen del subsistema de script de inicio, no se ejecutan, y está documentado que esto es lo que sucederá si coloca un archivo con ese nombre en/etc/rc*.d
y cuando se hace, se hace a propósito. La convención de nombrar archivos destinados a ser obtenidos en lugar de ejecutarse de esta manera también se sigue en otro lugar, pero no universalmente.Es cierto que los archivos destinados a ser obtenidos de esta manera tienen que cuidar qué configuraciones pueden estar presentes en el entorno de su interlocutor que puedan afectar el comportamiento del shell, pero entonces el protocolo acordado idealmente debería prometer un entorno de ejecución predecible.
fuente
zsh
tiene una característica que permite restaurar las opciones a un conjunto de conocimientos en un contexto local (emulate -L zsh
) que se usa ampliamente en todas las extensiones incluidas con zsh y escritas como código zsh. Vea cómo el sistema de finalización de bash falla miserablemente si configura algunas opciones comofailglob
.#! /bin/csh -f
lugar de,#! /bin/csh
por ejemplo.zshenv
. ¡Cuidado con lo que poneszshenv
por esa razón!emulate -L
en este caso) al comentar una de mis respuestas, y lo aprecio.~/.zshenv
(donde desea forzar la configuración (generalmente env vars) para todos los zsh's (interactivos o no) invocados bajo su nombre, y generalmente no se utilizan, excepto para solucionar algún otro problema que no sea zsh) está separado del~/.zshrc
(el shell de personalización), por lo que es una característica, no un error. (puede usar zsh -f) Un error es cuando algunos shells de bash no interactivos leen~/.bashrc
(como sobre ssh y tiene que agregar código para protegerse de eso), o algún bash interactivo (los de inicio de sesión) no lo leen (y de nuevo, debe agregar código en su~/.bash_profile
para evitarlo).