Cambiar / bin / sh enlace temporalmente

9

Tengo una pieza de software que requiere /bin/shser Bash, pero para Ubuntu el valor predeterminado es Dash y quiero mantenerlo predeterminado; No quiero cambiarlo a Bash de forma permanente.

¿Hay alguna manera de cambiarlo solo para una sesión de terminal en ejecución? Entonces, ¿un programa que se ejecute en este terminal verá /bin/shvinculado a bash pero el resto del sistema seguirá viendo Dash? ¿O puedo engañar al software para que lo vea /bin/shcomo Bash aunque no lo sea?

No escribí este software y piratearlo para usarlo en /bin/bashlugar de /bin/shno es realmente una opción.

corwin
fuente
2
Puede cambiarlo temporalmente, pero no (AFAIK) limita el alcance a una sola sesión de terminal. Ver por ejemplo / bin / sh es un enlace simbólico que no apunta a / bin / bash
steeldriver
2
Posiblemente de interés: unix.stackexchange.com/questions/468289/…
ejjl
77
Hagas lo que hagas, también informa de esto como un error para el software en cuestión. Porque asumir /bin/shque bash es un error y causa problemas reales (como lo está descubriendo). Si nadie se queja, es posible que nunca se cambie.
marcelm
1
@SergiyKolodyazhnyy Si el error no causa problemas en la (s) única (s) plataforma (s) que admiten, entonces probablemente puedan salirse con la suya. Sin embargo, sigue siendo un error.
marcelm
1
El software es Petalinux lanzado por una compañía "pequeña" llamada Xilinx, y de acuerdo con la documentación Ubuntu 16.04 es compatible (junto con CentOS y RHEL), por lo que diría que es un error.
corwin

Respuestas:

10

Dos respuestas ya sugieren monturas chrooting y bind, y hay una tercera opción estrechamente relacionada: montar espacios de nombres . Con el unshareprograma , puede crear un nuevo espacio de nombres de montaje, y los montajes dentro de este espacio de nombres no afectarán a otros espacios de nombres.

Por ejemplo, en una terminal, hago:

muru|[0] ~ sudo unshare -m /bin/bash
root@muru-1604:~# sudo mount --bind /bin/bash /bin/sh
root@muru-1604:~# /bin/sh --version
GNU bash, version 4.4.18(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
root@muru-1604:~# sudo -iu muru
muru|[0] ~ /bin/sh --version  # propagates
GNU bash, version 4.4.18(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Y en otro:

$ /bin/sh --version
/bin/sh: 0: Illegal option --

Entonces podría ejecutar este programa inflexible en su propio espacio de nombres de montaje.

muru
fuente
14

Si es un guión, simplemente llame al guión como

bash scriptname.sh

No es necesario cambiar los enlaces en absoluto.

Para el ejecutable compilado, puede ir a la ruta chroot:

mkdir rootfs
cp -a /usr rootfs/
cp -a /lib rootfs/
cp -a /lib64 rootfs/
cp /bin/bash  rootfs/bin/sh
cp yourprogram  rootfs/
sudo chroot rootfs  sh

Y luego ejecuta tu programa o sudo chroot rootfs /yourprogram


Sin embargo, en la práctica no hay ninguna razón por la que no pueda usarlo /bin/bashcomo enlace simbólico /bin/sh. De hecho, antes de la versión 6.10, Ubuntu usaba /bin/bashcomo /bin/sh, y luego cambiaron debido a /bin/shuna implementación mucho más rápida y ágil de POSIX /bin/sh(es decir, se adhiere al estándar POSIX sobre cómo deberían comportarse las utilidades del sistema operativo y el sistema operativo tipo Unix y implementar algunos de sus componentes internos), y debido a razones de portabilidad. Recomiendo leer la respuesta de Gilles también para notas históricas sobre cómo /bin/dashsurgió. En cuanto a la compatibilidad, los scripts escritos para dashusar las funciones POSIX se ejecutarán con bashun shell predeterminado perfectamente bien. Por lo general, es al revés lo que causa problemas:bashtiene características que no son necesarias /bin/sh, como la <<<sintaxis o las matrices.

Además, el comando en cuestión probablemente esté escrito con RHEL o CentOS en mente, que se utiliza /bin/bashcomo un enlace simbólico para /bin/sh, sugiere dos cosas: probablemente apuntaron a un sistema operativo específico y no se adhirieron a los principios POSIX. En ese caso, también sería una buena idea verificar qué otras cosas requiere el comando, ya que si realmente está escrito con otro sistema operativo en mente, podría tener más problemas que simplemente volver a vincular /bin/sh.

Sergiy Kolodyazhnyy
fuente
2
Jajaja La vida puede ser tan simple :-)
PerlDuck
1
Te ganaste mi
voto a favor
@JoshuaBesneatte ¡Gracias! Me alegra que mi respuesta sea útil
Sergiy Kolodyazhnyy
3
+1 y podría ser mejor crear enlaces duros en lugar de copias (a través de lno cp -l).
David Foerster
1
Considerar en mount --rbind --make-rslavelugar de cp -r. También se puede hacer de solo lectura. También sudo chrootejecuta el script como root, lo que podría no ser óptimo.
Roman Odaisky
5

Una posibilidad sería un montaje de enlace de un solo archivo. Para ello, se monta el archivo /bin/bashsimplemente sobre /bin/dash lo que bashtipo de cubiertas o cueros dash. Estos son los pasos (incluido el reverso):

root@myhost:~# cd /bin

# situation before (bash and dash are different):
root@myhost:/bin# ls -l *sh*
-rwxr-xr-x 1 root root 1113504 Apr  4 20:30 bash
-rwxr-xr-x 1 root root  121432 Jan 25  2018 dash
lrwxrwxrwx 1 root root       4 Jul 13 11:38 sh -> dash
...

# mount /bin/bash over /bin/dash:
root@myhost:/bin# mount --bind /bin/bash /bin/dash

# situation now (bash and dash are the same):
root@myhost:/bin# ls -l *sh*
-rwxr-xr-x 1 root root 1113504 Apr  4 20:30 bash
-rwxr-xr-x 1 root root 1113504 Apr  4 20:30 dash
lrwxrwxrwx 1 root root       4 Jul 13 11:38 sh -> dash
...

# Now everything that runs `/bin/sh` in fact uses `/bin/bash`.

# check what the symlink "sh" says:
root@myhost:/bin# sh --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
...

# undo the mount:
root@myhost:/bin# umount /bin/dash 

# situation now (bash and dash are different again):
root@myhost:/bin# ls -l *sh*
-rwxr-xr-x 1 root root 1113504 Apr  4 20:30 bash
-rwxr-xr-x 1 root root  121432 Jan 25  2018 dash
lrwxrwxrwx 1 root root       4 Jul 13 11:38 sh -> dash
...

# check what the symlink "sh" now says:
root@myhost:/bin# sh --version
sh: 0: Illegal option --

Sin embargo, no intenté ocultarmount --bind /bin/bash /bin/sh directamente el enlace simbólico. El truco anterior solo hace que bash y dash sean idénticos, por lo que se refiere a aunque apunta . Además, esta es una solución para todo el sistema, no solo para la ventana de terminal actual.mountshbashdash


Debo confesar que esto podría ser excesivo y que simplemente cambiar el enlace simbólico temporalmente es mucho más fácil. Solo quería mostrar otra forma posible.

PerlDuck
fuente
1

Debería poder cambiarlo solo para la sesión actual utilizando un alias. Antes de ejecutar su comando en la terminal:

alias sh=bash

Esto será temporal y solo estará activo en el terminal desde el que se ejecutó.

SIN EMBARGO: Esto NO FUNCIONARÁ si su script usa rutas absolutas.

Buena idea como tal, pero si el software llama directamente / bin / sh con un nombre de ruta explícito, no funcionará. De todos modos, ese software no parece estar muy bien diseñado haciendo tales suposiciones. Probablemente lo ejecutaría desde un script que prepara y restablece el entorno adecuado si tuviera que usarlo. - vanadio

Desafortunadamente, "piratear" el script podría ser su única opción. Por convo con @vanadium, puede crear un script de envoltura como este:

#!/bin/bash
sudo ln -sf /bin/bash /bin/sh
/run/my/script
sudo ln -sf /bin/dash /bin/sh

Sin embargo, durante la duración de su script, es mejor que no espere que nada en su sistema requiera un guión explícito.

Joshua Besneatte
fuente
3
Buena idea como tal, pero si el software llama directamente / bin / sh con un nombre de ruta explícito, no funcionará. De todos modos, ese software no parece estar muy bien diseñado haciendo tales suposiciones. Probablemente lo ejecutaría desde un script que prepara y restablece el entorno adecuado si tuviera que usarlo.
vanadio
Me interesaría ver cómo harías para preparar el medio ambiente. usarías chroot?
Joshua Besneatte
No tenía ideas tan ambiciosas. Estaba pensando en un script que temporalmente tendría un enlace sh para bash y restablecer cuando haya terminado. El principal problema en esta pregunta es con la "pieza de software" en cuestión, creo.
vanadio
¿Qué pasaría si algo más necesitara guión mientras se movía el enlace simbólico ... algo así como ln -sf / bin / bash / bin / sh al principio y ln -sf / bin / dash / bin / sh cuando se hace?
Joshua Besneatte
La mayoría de los otros procesos probablemente usarán felizmente bash en lugar de guión si se cambia el enlace. Sí, en ese vano, pero para imitar la situación actual, haría enlaces relativos, es decir, "cd / bin; ln -sf bash sh", pero ese es probablemente un detalle purista que no importará en la práctica.
vanadio