webentwicklung-frage-antwort-db.com.de

Ändern / bin / sh Link vorübergehend

Ich habe eine Software, die erfordert, dass /bin/sh Bash ist, aber für Ubuntu ist die Standardeinstellung Dash, und ich möchte sie als Standardeinstellung beibehalten. Ich möchte es nicht dauerhaft in Bash ändern.

Gibt es eine Möglichkeit, es nur für eine laufende Terminalsitzung zu ändern? Ein Programm, das in diesem Terminal ausgeführt wird, sieht /bin/sh, das mit Bash verknüpft ist, aber der Rest des Systems sieht immer noch Dash? Oder kann ich die Software täuschen, um /bin/sh als Bash zu sehen, auch wenn dies nicht der Fall ist?

Ich habe diese Software nicht geschrieben und es gehackt, um /bin/bash anstelle von /bin/sh zu verwenden. Dies ist eigentlich keine Option.

8
corwin

Zwei Antworten deuten bereits auf das Chrooten und Binden von Mounts hin, und es gibt eine dritte, eng verwandte Option: Mount-Namespaces . Mit dem Programm unshare können Sie einen neuen Mount-Namespace erstellen, und Mounts in diesem Namespace wirken sich nicht auf andere Namespaces aus.

In einem Terminal mache ich zum Beispiel:

muru|[0] ~ Sudo unshare -m /bin/bash
[email protected]:~# Sudo mount --bind /bin/bash /bin/sh
[email protected]:~# /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.
[email protected]:~# 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.

Und in einem anderen:

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

Sie können dieses unflexible Programm also in einem eigenen Mount-Namespace ausführen.

10
muru

Wenn es sich um ein Skript handelt, rufen Sie das Skript einfach als auf

bash scriptname.sh

Keine Notwendigkeit, Links zu ändern.

Für kompilierte ausführbare Dateien können Sie die Chroot-Route verwenden:

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

Und dann starte dein Programm oder Sudo chroot rootfs /yourprogram


In der Praxis gibt es jedoch keinen Grund, warum Sie /bin/bash nicht als Symlink zu /bin/sh verwenden können. Tatsächlich vor Version 6.1 verwendete Ubuntu /bin/bash als /bin/sh, und dann wechselten sie, da /bin/sh eine viel schnellere und schlankere Implementierung von POSIX /bin/sh war (das heißt, es entspricht dem POSIX-Standard, wie Unix-ähnliche Betriebssystemdienstprogramme und Betriebssysteme sollten sich (aus Gründen der Portabilität) verhalten und einige ihrer Interna implementieren. Ich empfehle dringend lese Gilles 'Antwort auch für historische Notizen darüber, wie es zu /bin/dash kam. Aus Kompatibilitätsgründen werden Skripts, die für dash mit POSIX-Funktionen geschrieben wurden, ausgeführt, wobei bash eine Standard-Shell ist. Normalerweise ist es umgekehrt, was zu Problemen führt - bash verfügt über Funktionen, die von /bin/sh nicht benötigt werden, z. B. <<< syntax oder Arrays.

Darüber hinaus ist der betreffende Befehl wahrscheinlich für RHEL oder CentOS geschrieben, die /bin/bash als Symlink zu /bin/sh verwenden. Dies deutet auf zwei Dinge hin: Sie haben wahrscheinlich ein bestimmtes Betriebssystem zum Ziel und halten sich nicht an POSIX-Prinzipien. In diesem Fall ist es auch eine gute Idee, zu überprüfen, welche anderen Dinge der Befehl erfordert, da Sie möglicherweise auf mehr Probleme stoßen, als nur /bin/sh erneut zu verknüpfen, wenn er wirklich mit einem anderen Betriebssystem geschrieben wurde.

14

Eine Möglichkeit wäre ein bind mount einer einzelnen Datei. Um dies zu tun, müssen Sie mount die Datei /bin/bash nur over/bin/dash also bash Art von Covers oder Hides dash . Hier sind die Schritte (einschließlich der Rückseite):

[email protected]:~# cd /bin

# situation before (bash and dash are different):
[email protected]:/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:
[email protected]:/bin# mount --bind /bin/bash /bin/dash

# situation now (bash and dash are the same):
[email protected]:/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:
[email protected]:/bin# sh --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
...

# undo the mount:
[email protected]:/bin# umount /bin/dash 

# situation now (bash and dash are different again):
[email protected]:/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:
[email protected]:/bin# sh --version
sh: 0: Illegal option --

Ich habe nicht versucht, mount --bind /bin/bash /bin/sh direkt hide den Symlink zu setzen. Der obige mount Trick macht Bash und Dash nur identisch, so dass sh auf bash verweist, obwohl er auf dash verweist. Dies ist auch eine systemweite Lösung, nicht nur für das aktuelle Terminalfenster.


Ich muss gestehen, das könnte übertrieben sein und es ist viel einfacher, den Symlink vorübergehend zu ändern. Ich wollte nur einen anderen möglichen Weg zeigen.

5
PerlDuck

Sie sollten es nur für die aktuelle Sitzung mithilfe eines Alias ​​ändern können. Bevor Sie Ihren Befehl im Terminal ausführen:

alias sh=bash

Dies ist temporär und nur in dem Terminal aktiv, von dem aus es ausgeführt wurde.

Allerdings: Dies funktioniert nicht, wenn Ihr Skript absolute Pfade verwendet.

Gute Idee als solche, aber wenn die Software direkt/bin/sh mit einem expliziten Pfadnamen aufruft, wird es nicht funktionieren. Wie auch immer, diese Software scheint nicht sehr richtig entworfen zu sein, wenn man solche Annahmen trifft. Ich würde es wahrscheinlich von einem Skript ausführen, das die richtige Umgebung vorbereitet und zurücksetzt, wenn ich es überhaupt verwenden müsste. - Vanadium

Leider ist das "Hacken" des Skripts möglicherweise Ihre einzige Option. Per Convo mit @vanadium können Sie ein Wrapper-Skript wie folgt erstellen:

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

Während der Dauer Ihres Skripts hoffen Sie jedoch besser, dass nichts auf Ihrem System explizit einen Gedankenstrich erfordert.

1