Modifier le lien / bin / sh temporairement

9

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

Existe-t-il un moyen de le modifier uniquement pour une session de terminal en cours d'exécution? Un programme exécuté dans ce terminal verra donc /bin/shlié à bash mais le reste du système verra toujours Dash? Ou puis-je tromper le logiciel pour le voir /bin/shcomme Bash même si ce n'est pas le cas?

Je n'ai pas écrit ce logiciel et le pirater pour l'utiliser /bin/bashau lieu de /bin/shn'est pas vraiment une option.

corwin
la source
2
Vous pouvez le modifier temporairement - mais pas (AFAIK) limiter la portée à une seule session de terminal. Voir par exemple / bin / sh est un lien symbolique qui ne pointe pas vers / bin / bash
steeldriver
2
Peut-être d'intérêt: unix.stackexchange.com/questions/468289/…
ejjl
7
Quoi que vous fassiez, veuillez également signaler cela comme un bug pour le logiciel en question. Parce que l' hypothèse /bin/shest bash est un bug, et il provoque des problèmes réels (comme vous savoir). Si personne ne se plaint, cela ne changera peut-être jamais.
marcelm
1
@SergiyKolodyazhnyy Si le bogue ne cause pas de problèmes sur les seules plates-formes qu'ils prennent en charge, ils peuvent probablement s'en tirer. C'est quand même un bug.
marcelm
1
Le logiciel est Petalinux publié par une "petite" entreprise appelée Xilinx, et selon la documentation Ubuntu 16.04 est pris en charge (avec CentOS et RHEL), donc je dirais que c'est un bug.
corwin

Réponses:

10

Deux réponses suggèrent déjà de chrooter et de lier des montures, et il y a une troisième option étroitement liée: monter des espaces de noms . En utilisant le unshareprogramme , 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.

muru
la source
14

Si c'est un script, appelez simplement le script comme

bash scriptname.sh

Pas besoin de changer de liens du tout.

Pour l'exécutable compilé, vous pouvez aller 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 puis exécutez votre programme ou sudo chroot rootfs /yourprogram


Cependant, dans la pratique, il n'y a aucune raison pour laquelle vous ne pouvez pas l'utiliser /bin/bashcomme lien symbolique vers /bin/sh. En fait, avant la version 6.10, Ubuntu utilisait /bin/bashas /bin/sh, puis ils ont changé en raison d' /bin/shune implémentation beaucoup plus rapide et plus légère de POSIX /bin/sh(c'est-à-dire qu'il respecte la norme POSIX pour la façon dont les utilitaires et les systèmes d'exploitation de type Unix devraient se comporter et implémenter certains de leurs internes), et pour des raisons de portabilité. Je recommande fortement de lire la réponse de Gilles également pour des notes historiques sur la façon dont cela /bin/dashs'est produit. Quant à la compatibilité, les scripts écrits pour dashutiliser les fonctionnalités POSIX fonctionneront avec bashun shell par défaut parfaitement bien. Habituellement, c'est l'inverse qui cause des problèmes -basha 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 en gardant à l'esprit RHEL ou CentOS, qui utilise /bin/bashun lien symbolique vers /bin/sh, suggère deux choses: ils ciblaient probablement un système d'exploitation spécifique et n'adhéraient pas aux principes POSIX. Dans ce cas, ce serait également une bonne idée de vérifier les autres éléments requis par la commande, car si elle est vraiment écrite avec un autre système d'exploitation à l'esprit, vous pourriez rencontrer plus de problèmes que la simple reconnexion /bin/sh.

Sergiy Kolodyazhnyy
la source
2
LOL. La vie peut être si simple :-)
PerlDuck
1
Vous avez gagné mon vote positif :)
Joshua Besneatte
@JoshuaBesneatte Merci! Heureux que vous trouviez ma réponse utile
Sergiy Kolodyazhnyy
3
+1 et il pourrait être préférable de créer des liens physiques au lieu de copies (via lnou cp -l).
David Foerster
1
Considérez mount --rbind --make-rslaveplutôt que cp -r. Peut également être mis en lecture seule. Exécute également sudo chrootle script en tant que root, ce qui peut ne pas être optimal.
Roman Odaisky
5

Une possibilité serait un montage de liaison d'un seul fichier. Pour ce faire, vous montez le fichier un /bin/bashpeu plus de /bin/dash sorte bashsorte de couvertures ou de masques 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 masquermount --bind /bin/bash /bin/sh directement le lien symbolique. L' astuce ci-dessus rend simplement bash et dash identiques, ce qui fait référence à bien qu'il pointe vers . En outre, il s'agit d'une solution à l'échelle du système, non seulement pour la fenêtre de terminal actuelle.mountshbashdash


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

PerlDuck
la source
1

Vous devriez pouvoir le modifier 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 uniquement actif 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 soi, mais si le logiciel appelle directement / bin / sh avec un chemin d'accès explicite, cela ne fonctionnera pas. Quoi qu'il en soit, ce logiciel ne semble pas être très bien conçu en faisant 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. - vanadium

Malheureusement, le "piratage" du script pourrait être votre seule option. Par convo avec @vanadium, vous pouvez créer un script wrapper comme celui-ci:

#!/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, vous feriez mieux d'espérer que rien sur votre système ne nécessite explicitement un tiret.

Joshua Besneatte
la source
3
Bonne idée en soi, mais si le logiciel appelle directement / bin / sh avec un chemin d'accès explicite, cela ne fonctionnera pas. Quoi qu'il en soit, ce logiciel ne semble pas être très bien conçu en faisant 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.
vanadium
Je serais intéressé de voir comment vous procéderiez pour préparer l'environnement. utiliseriez-vous chroot?
Joshua Besneatte
Je n'avais pas d'idées aussi ambitieuses. Je pensais juste à un script qui aurait temporairement un lien sh vers bash et serait réinitialisé une fois terminé. Le problème principal de cette question concerne le "logiciel" concerné, je pense.
vanadium
que se passerait-il si quelque chose d'autre avait besoin d'un tiret pendant que le lien symbolique était déplacé ... quelque chose comme ln -sf / bin / bash / bin / sh au début et ln -sf / bin / dash / bin / sh une fois terminé?
Joshua Besneatte
La plupart des autres processus utiliseront probablement heureusement bash au lieu de dash si le lien est modifié. Oui, en vain, mais pour imiter la situation actuelle, je ferais des liens relatifs, c'est-à-dire "cd / bin; ln -sf bash sh", mais c'est probablement un détail puriste qui n'aura pas d'importance en pratique.
vanadium