Zmień tymczasowo link / bin / sh

9

Mam oprogramowanie, które wymaga /bin/shBash, ale dla Ubuntu domyślnym jest Dash i chcę zachować to domyślne; Nie chcę na stałe zmieniać go na Bash.

Czy istnieje sposób, aby to zmienić tylko w przypadku uruchomionej sesji terminala? Więc program działający w tym terminalu będzie widział /bin/shlink do bash, ale reszta systemu nadal będzie widzieć Dash? Czy mogę oszukać oprogramowanie, aby wyświetlało się /bin/shjako Bash, nawet jeśli nie jest?

Nie napisałem tego oprogramowania i włamanie go do użycia /bin/bashzamiast /bin/shnie jest tak naprawdę opcją.

corwin
źródło
2
Możesz go zmienić tymczasowo - ale nie (AFAIK) ogranicz zakres do pojedynczej sesji terminala. Zobacz na przykład / bin / sh to dowiązanie symboliczne, które nie wskazuje na / bin / bash
steeldriver
2
Prawdopodobnie interesujące: unix.stackexchange.com/questions/468289/…
ejjl
7
Cokolwiek zrobisz, zgłoś to również jako błąd dla danego oprogramowania. Bo zakładając, /bin/shjest bash to błąd, a to powoduje, że rzeczywiste problemy (jak jesteś ustaleniu). Jeśli nikt nie narzeka, może się nigdy nie zmienić.
marcelm
1
@SergiyKolodyazhnyy Jeśli błąd nie powoduje problemów na jedynych platformach, które obsługują, prawdopodobnie uda się go uniknąć. Jednak nadal jest to błąd.
marcelm
1
Oprogramowanie to Petalinux wydane przez „małą” firmę Xilinx i zgodnie z dokumentacją obsługiwany jest Ubuntu 16.04 (wraz z CentOS i RHEL), więc powiedziałbym, że to błąd.
corwin

Odpowiedzi:

10

Dwie odpowiedzi już sugerują chrootowanie i łączenie wierzchowców, a istnieje trzecia, ściśle powiązana opcja: przestrzenie nazw montowania . Za pomocą unshareprogramu możesz utworzyć nową przestrzeń nazw montowań, a montowania w tej przestrzeni nazw nie będą miały wpływu na inne przestrzenie nazw.

Na przykład w jednym terminalu wykonuję:

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.

A w innym:

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

Abyś mógł uruchomić ten nieelastyczny program we własnej przestrzeni nazw montowania.

muru
źródło
14

Jeśli jest to skrypt, po prostu wywołaj go jako

bash scriptname.sh

W ogóle nie trzeba zmieniać linków.

Aby skompilować plik wykonywalny, możesz wybrać trasę 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

A następnie uruchom swój program lub sudo chroot rootfs /yourprogram


Jednak w praktyce nie ma powodu, dla którego nie można użyć /bin/bashjako dowiązania symbolicznego /bin/sh. W rzeczywistości przed wersją 6.10 Ubuntu używało/bin/bash jako /bin/sh, a następnie przełączyło się z powodu /bin/shznacznie szybszej i szczuplejszej implementacji POSIX /bin/sh(to znaczy, że jest zgodny ze standardem POSIX, jeśli chodzi o to, jak powinny zachowywać się narzędzia systemu operacyjnego i systemu operacyjnego uniksopodobnego oraz zaimplementować niektóre z ich elementów wewnętrznych) oraz ze względu na przenośność. Zdecydowanie polecam również przeczytanie odpowiedzi Gillesa, aby zapoznać się z historycznymi notatkami na temat tego, jak /bin/dashpowstało. Jeśli chodzi o kompatybilność, skrypty napisane w celu dashkorzystania z funkcji POSIX będą działały z bashdomyślną powłoką idealnie w porządku. Zwykle jest na odwrót, co powoduje problemy -bash funkcjami, które nie są wymagane /bin/sh, takie jak <<<składnia lub tablice.

Dodatkowo, to polecenie jest prawdopodobnie napisane z myślą o RHEL lub CentOS, które używa /bin/bashjako dowiązania symbolicznego /bin/sh, sugeruje dwie rzeczy: prawdopodobnie celowały w określony system operacyjny i nie przestrzegały zasad POSIX. W takim przypadku dobrym pomysłem byłoby również sprawdzenie, jakich innych rzeczy wymaga polecenie, ponieważ jeśli jest napisane z myślą o innym systemie operacyjnym, możesz napotkać więcej problemów niż tylko ponowne połączenie /bin/sh.

Sergiy Kolodyazhnyy
źródło
2
LOL. Życie może być takie proste :-)
PerlDuck
1
Zasłużyłem na moje poparcie :)
Joshua Besneatte
@JoshuaBesneatte Dziękujemy! Cieszę się, że moja odpowiedź jest przydatna
Sergiy Kolodyazhnyy,
3
+1 i może być lepiej utworzyć twarde linki zamiast kopii (przez lnlub cp -l).
David Foerster,
1
Rozważ mount --rbind --make-rslaveraczej niż cp -r. Może być również ustawiony tylko do odczytu. Również sudo chrooturuchamia skrypt jako root, który może nie być optymalna.
Roman Odaisky,
5

Jedną z możliwości może być podłączenie jednego pliku. Aby to zrobić, należy zamontować plik /bin/bashtuż nad /bin/dash tak bashrodzaj osłon lub ukrywa dash. Oto kroki (w tym odwrotne):

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

I nie próbował mount --bind /bin/bash /bin/shbezpośrednio ukryć dowiązania, choć. Powyższa mountsztuczka sprawia, że ​​bash i myślnik są identyczne, więc shodnosi się do tego, bashchociaż wskazuje dash. Jest to również rozwiązanie systemowe, nie tylko dla bieżącego okna terminala.


Muszę wyznać, że może to być przesada, a po prostu tymczasowa zmiana dowiązania symbolicznego jest znacznie łatwiejsza. Chciałem tylko pokazać inny możliwy sposób.

PerlDuck
źródło
1

Powinieneś być w stanie to zmienić tylko dla bieżącej sesji przy użyciu aliasu. Przed uruchomieniem polecenia w terminalu:

alias sh=bash

Będzie to tymczasowe i aktywne tylko w terminalu, z którego zostało wykonane.

JEDNAK: NIE DZIAŁA, jeśli skrypt używa ścieżek bezwzględnych.

Dobry pomysł jako taki, ale jeśli oprogramowanie wywołuje bezpośrednio / bin / sh z jawną nazwą ścieżki, nie będzie działać. W każdym razie oprogramowanie to nie wydaje się być właściwie zaprojektowane przy takich założeniach. Prawdopodobnie uruchomiłbym go ze skryptu, który przygotowuje i resetuje właściwe środowisko, gdybym musiał go w ogóle używać. - wanad

Niestety „hakowanie” skryptu może być Twoją jedyną opcją. Na konwój z @vanadium możesz utworzyć skrypt otoki w następujący sposób:

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

Jednak podczas trwania skryptu lepiej jest mieć nadzieję, że nic w systemie nie wymaga wyraźnego myślnika.

Joshua Besneatte
źródło
3
Dobry pomysł jako taki, ale jeśli oprogramowanie wywołuje bezpośrednio / bin / sh z jawną nazwą ścieżki, nie będzie działać. W każdym razie oprogramowanie to nie wydaje się być właściwie zaprojektowane przy takich założeniach. Prawdopodobnie uruchomiłbym go ze skryptu, który przygotowuje i resetuje właściwe środowisko, gdybym musiał go w ogóle używać.
wanad
Byłbym zainteresowany, aby zobaczyć, jak poszedłbyś na temat przygotowania środowiska. czy użyłbyś chroot?
Joshua Besneatte,
Nie miałem tak ambitnych pomysłów. Właśnie myślałem o skrypcie, który po zakończeniu miałby tymczasowo link sh do bash i zresetował się. Myślę, że głównym problemem w tym pytaniu jest „oprogramowanie”.
wanad
co by się stało, gdyby coś innego wymagało kreski podczas przenoszenia dowiązania symbolicznego .... coś takiego jak ln -sf / bin / bash / bin / sh na początku i ln -sf / bin / dash / bin / sh po zakończeniu?
Joshua Besneatte,
Większość innych procesów prawdopodobnie chętnie użyje bash zamiast myślnika, jeśli łącze zostanie zmienione. Tak, na próżno, ale aby naśladować obecną sytuację, stworzyłbym odnośniki względne, tj. „Cd / bin; ln -sf bash sh”, ale jest to prawdopodobnie purystyczny szczegół, który nie będzie miał znaczenia w praktyce.
wanad