Ubah / bin / sh tautan sementara

9

Saya memiliki perangkat lunak yang /bin/shharus Bash, tetapi untuk Ubuntu defaultnya adalah Dash dan saya ingin tetap menggunakannya sebagai default; Saya tidak ingin mengubahnya ke Bash secara permanen.

Apakah ada cara untuk mengubahnya hanya untuk sesi terminal berjalan? Jadi program yang berjalan di terminal ini akan melihat /bin/shditautkan ke bash tetapi sisa sistem masih akan melihat Dash? Atau bisa saya mengelabui perangkat lunak untuk melihat /bin/shseperti Bash bahkan jika tidak nya?

Saya tidak menulis perangkat lunak ini dan meretasnya untuk digunakan, /bin/bashbukan /bin/shbenar-benar pilihan.

corwin
sumber
2
Anda dapat mengubahnya sementara - tetapi tidak (AFAIK) membatasi ruang lingkup untuk sesi terminal tunggal. Lihat misalnya / bin / sh adalah tautan simbolik yang tidak mengarah ke / bin / bash
steeldriver
7
Apa pun yang Anda lakukan, tolong juga laporkan ini sebagai bug untuk perangkat lunak yang dimaksud. Karena asumsi /bin/shadalah bash adalah bug, dan hal itu menyebabkan masalah yang sebenarnya (karena Anda mencari tahu). Jika tidak ada yang mengeluh, itu mungkin tidak akan pernah berubah.
marcelm
1
@SergiyKolodyazhnyy Jika bug tidak menyebabkan masalah pada satu-satunya platform yang mereka dukung, maka mereka mungkin bisa lolos begitu saja. Ini masih bug.
marcelm
1
Perangkat lunaknya adalah Petalinux yang dirilis oleh sebuah perusahaan "kecil" bernama Xilinx, dan menurut dokumentasi Ubuntu 16.04 didukung (bersama dengan CentOS dan RHEL), jadi saya akan mengatakan itu bug.
corwin

Jawaban:

10

Dua jawaban sudah menyarankan chroot dan mengikat mount, dan ada opsi ketiga, terkait erat: mount namespaces . Menggunakan unshareprogram ini , Anda dapat membuat mount namespace baru, dan mount dalam namespace ini tidak akan memengaruhi ruang nama lain.

Sebagai contoh, dalam satu terminal, saya lakukan:

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.

Dan di tempat lain:

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

Jadi Anda bisa menjalankan program tidak fleksibel ini di mount namespace-nya sendiri.

muru
sumber
14

Jika ini skrip, panggil saja skrip tersebut sebagai

bash scriptname.sh

Tidak perlu mengubah tautan sama sekali.

Untuk file executable yang bisa dieksekusi, Anda bisa menggunakan 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

Dan kemudian jalankan program Anda atau sudo chroot rootfs /yourprogram


Namun, dalam praktiknya tidak ada alasan mengapa Anda tidak dapat menggunakan /bin/bashsebagai symlink /bin/sh. Bahkan, sebelum versi 6.10 Ubuntu digunakan /bin/bashsebagai /bin/sh, dan kemudian mereka beralih karena /bin/shmenjadi lebih cepat, implementasi lebih ramping dari POSIX /bin/sh(yaitu, mematuhi standar POSIX untuk bagaimana utilitas sistem operasi dan sistem operasi Unix-like dan OS harus berperilaku dan mengimplementasikan beberapa internal mereka), dan karena alasan portabilitas. Saya sangat merekomendasikan membaca jawaban Gilles juga untuk catatan sejarah tentang bagaimana hal itu /bin/dashterjadi. Adapun kompatibilitas, skrip yang ditulis untuk dashmenggunakan fitur POSIX akan berjalan dengan bashmenjadi shell default baik-baik saja. Biasanya, sebaliknya yang menyebabkan masalah -bashmemiliki fitur yang tidak diperlukan oleh /bin/sh, seperti <<<sintaks atau array.

Selain itu, perintah yang dimaksud mungkin ditulis dengan RHEL atau CentOS dalam pikiran, yang memang digunakan /bin/bashsebagai symlink /bin/sh, menyarankan dua hal: mereka mungkin menargetkan OS tertentu dan tidak mematuhi prinsip-prinsip POSIX. Dalam hal ini, itu juga merupakan ide yang baik untuk memeriksa hal-hal lain yang diperlukan oleh perintah, karena jika itu benar-benar ditulis dengan OS lain dalam pikiran, Anda mungkin mengalami lebih banyak masalah daripada hanya menghubungkan kembali /bin/sh.

Sergiy Kolodyazhnyy
sumber
2
LOL. Hidup bisa sangat sederhana :-)
PerlDuck
1
Anda mendapatkan upvote saya :)
Joshua Besneatte
@JoshuaBesneatte Terima kasih! Senang Anda menemukan jawaban saya bermanfaat
Sergiy Kolodyazhnyy
3
+1 dan mungkin lebih baik membuat tautan keras daripada salinan (via lnatau cp -l).
David Foerster
1
Pertimbangkan mount --rbind --make-rslavedaripada cp -r. Dapat dibuat hanya-baca juga. Juga sudo chrootmenjalankan skrip sebagai root yang mungkin tidak optimal.
Roman Odaisky
5

Satu kemungkinan akan menjadi bind mount dari satu file. Untuk melakukan ini, Anda memasang file /bin/bashdi atas /bin/dash sehingga bashsemacam penutup atau menyembunyikan dash. Berikut langkah-langkahnya (termasuk sebaliknya):

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

Saya tidak mencoba untuk menyembunyikan symlink mount --bind /bin/bash /bin/shsecara langsung . Trik di atas hanya membuat bash dan dash identik sehingga merujuk meskipun menunjuk ke . Juga, ini adalah solusi seluruh sistem, tidak hanya untuk jendela terminal saat ini.mountshbashdash


Saya harus akui, ini mungkin berlebihan dan hanya mengubah symlink sementara jauh lebih mudah. Saya hanya ingin menunjukkan cara lain yang mungkin.

PerlDuck
sumber
1

Anda harus dapat mengubahnya hanya untuk sesi saat ini dengan menggunakan alias. Sebelum menjalankan perintah Anda di terminal:

alias sh=bash

Ini bersifat sementara dan hanya aktif di terminal dari mana ia dieksekusi.

NAMUN: Ini TIDAK AKAN BEKERJA jika skrip Anda menggunakan jalur absolut.

Ide bagus seperti itu, tetapi jika perangkat lunak secara langsung memanggil / bin / sh dengan pathname eksplisit, itu tidak akan berfungsi. Bagaimanapun, perangkat lunak itu tampaknya tidak dirancang dengan sangat baik sehingga membuat asumsi seperti itu. Saya mungkin akan menjalankannya dari skrip yang menyiapkan dan mengatur ulang lingkungan yang tepat jika saya harus menggunakannya sama sekali. - vanadium

Sayangnya, "meretas" skrip mungkin satu-satunya pilihan Anda. Per obrolan dengan @vanadium, Anda dapat membuat skrip pembungkus seperti ini:

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

Namun, selama durasi skrip Anda, Anda lebih baik berharap tidak ada pada sistem Anda secara eksplisit membutuhkan tanda hubung.

Joshua Besneatte
sumber
3
Ide bagus seperti itu, tetapi jika perangkat lunak secara langsung memanggil / bin / sh dengan pathname eksplisit, itu tidak akan berfungsi. Bagaimanapun, perangkat lunak itu tampaknya tidak dirancang dengan sangat baik sehingga membuat asumsi seperti itu. Saya mungkin akan menjalankannya dari skrip yang menyiapkan dan mengatur ulang lingkungan yang tepat jika saya harus menggunakannya sama sekali.
vanadium
Saya akan tertarik untuk melihat bagaimana Anda akan mempersiapkan lingkungan. apakah Anda akan menggunakan chroot?
Joshua Besneatte
Saya tidak punya ide ambisius seperti itu. Saya hanya memikirkan sebuah skrip yang untuk sementara memiliki tautan sh ke bash dan mengatur ulang ketika selesai. Masalah utama dalam pertanyaan ini adalah dengan "perangkat lunak" yang bersangkutan, saya pikir.
vanadium
apa yang akan terjadi jika sesuatu yang lain memerlukan tanda hubung sementara tautan simbolis dipindahkan .... sesuatu seperti ln -sf / bin / bash / bin / sh di awal dan ln -sf / bin / dash / bin / sh ketika selesai?
Joshua Besneatte
Sebagian besar proses lain mungkin akan dengan senang hati menggunakan bash alih-alih dasbor jika tautan diubah. Ya, dalam kesia-siaan itu, tetapi untuk meniru situasi saat ini, saya akan membuat tautan relatif, yaitu "cd / bin; ln -sf bash sh", tapi itu mungkin detail murni yang tidak akan menjadi masalah dalam praktiknya.
vanadium