web-dev-qa-db-fra.com

Changer le lien / bin / sh temporairement

J'ai un logiciel qui requiert /bin/sh pour être Bash, mais pour Ubuntu, la valeur par défaut est Dash et je veux le conserver par défaut; Je ne veux pas le changer définitivement à Bash.

Est-il possible de le changer uniquement pour une session de terminal en cours d'exécution? Donc, un programme exécuté dans ce terminal verra que /bin/sh sera lié à bash mais le reste du système verra toujours Dash? Ou puis-je tromper le logiciel pour voir /bin/sh comme Bash même si ce n'est pas le cas?

Je n'ai pas écrit ce logiciel et le piratage pour utiliser /bin/bash au lieu de /bin/sh n'est pas vraiment une option.

8
corwin

Deux réponses suggèrent déjà de chrooter et de lier des montages, et il existe une troisième option étroitement liée: monter les espaces de noms . En utilisant le programme unshare , vous pouvez créer un nouvel espace de noms de montage et les montages dans cet espace de noms n'affecteront pas les autres espaces de noms.

Par exemple, dans un terminal, je fais:

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.

Et dans un autre:

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

Vous pouvez donc exécuter ce programme inflexible dans son propre espace de noms de montage.

10
muru

Si c'est un script, appelez-le simplement

bash scriptname.sh

Pas besoin de changer les liens du tout.

Pour les exécutables compilés, vous pouvez aller en chroot route

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

Et lancez ensuite votre programme ou Sudo chroot rootfs /yourprogram


Cependant, dans la pratique, il n'y a aucune raison pour que vous ne puissiez pas utiliser /bin/bash en tant que lien symbolique vers /bin/sh. En fait, avant la version 6.1 Ubuntu utilisait /bin/bash comme /bin/sh, puis ils ont basculé car /bin/sh était une implémentation beaucoup plus rapide et plus légère de POSIX /bin/sh (c’est-à-dire qu’elle adhérait au standard POSIX Les utilitaires de système d'exploitation et les systèmes d'exploitation de type Unix doivent se comporter et implémenter certains de leurs internes, et pour des raisons de portabilité. Je recommande fortement lisant la réponse de Gilles aussi pour les notes historiques sur la façon dont /bin/dash est apparu. En ce qui concerne la compatibilité, les scripts écrits pour dash à l'aide de fonctions POSIX s'exécutent avec bash comme shell par défaut parfaitement. Généralement, c’est l’inverse qui pose problème: bash possède des fonctionnalités qui ne sont pas requises par /bin/sh, comme la syntaxe <<< ou les tableaux.

De plus, la commande en question est probablement écrite avec RHEL ou CentOS à l'esprit, ce qui indique que /bin/bash est un lien symbolique vers /bin/sh, ce qui suggère deux choses: ils ciblaient probablement un système d'exploitation spécifique et ne respectaient pas les principes POSIX. Dans ce cas, il serait également judicieux de vérifier les autres éléments requis par la commande, car si elle est réellement écrite avec un autre système d'exploitation à l'esprit, vous risquez de rencontrer plus de problèmes que de simplement re-lier /bin/sh.

14
Sergiy Kolodyazhnyy

Une possibilité serait un bind mount d'un seul fichier. Pour ce faire, vous montez le fichier /bin/bash simplement finissez/bin/dash so bash sorte de cache ou cache dash. Voici les étapes (y compris l'inverse):

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 --

Cependant, je n'ai pas essayé de mount --bind /bin/bash /bin/sh directement masquer le lien symbolique. L'astuce ci-dessus mount rend simplement bash et dash identiques, de sorte que sh se réfère à bash bien qu'il pointe vers dash. En outre, il s'agit d'une solution à l'échelle du système, pas seulement pour la fenêtre de terminal actuelle.


Je dois avouer que cela pourrait être exagéré et que changer simplement le lien symbolique temporairement est beaucoup plus facile. Je voulais juste montrer une autre voie possible.

5
PerlDuck

Vous devriez pouvoir le changer uniquement pour la session en cours en utilisant un alias. Avant d'exécuter votre commande dans le terminal:

alias sh=bash

Ce sera temporaire et actif uniquement dans le terminal à partir duquel il a été exécuté.

CEPENDANT: Cela ne fonctionnera PAS si votre script utilise des chemins absolus.

Bonne idée en tant que telle, mais si le logiciel appelle directement/bin/sh avec un chemin explicite, cela ne fonctionnera pas. Quoi qu’il en soit, ce logiciel ne semble pas être très bien conçu et fait de telles hypothèses. Je l'exécuterais probablement à partir d'un script qui prépare et réinitialise l'environnement approprié si je devais l'utiliser du tout. - vanadium

Malheureusement, "pirater" le script pourrait être votre seule option. Par convo avec @vanadium, vous pouvez créer un script wrapper comme ceci:

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

Cependant, pendant la durée de votre script, il vaut mieux que rien ne demande explicitement un tiret sur votre système.

1
Joshua Besneatte