Saya ingin menjalankan subshell bash, (1) menjalankan beberapa perintah, (2) dan kemudian tetap dalam subshell itu untuk melakukan sesukaku. Saya dapat melakukan masing-masing ini secara individual:
Jalankan perintah menggunakan
-c
flag:$> bash -c "ls; pwd; <other commands...>"
namun, ia segera kembali ke shell "super" setelah perintah dijalankan. Saya juga bisa menjalankan subkulit interaktif:
Mulai
bash
proses baru :$> bash
dan itu tidak akan keluar dari subkulit sampai saya katakan secara eksplisit ... tapi saya tidak bisa menjalankan perintah awal. Solusi terdekat yang saya temukan adalah:
$> bash -c "ls; pwd; <other commands>; exec bash"
yang berfungsi, tetapi tidak seperti yang saya inginkan, karena menjalankan perintah yang diberikan dalam satu subkulit, dan kemudian membuka yang terpisah untuk interaksi.
Saya ingin melakukan ini pada satu baris. Setelah saya keluar dari subkulit, saya harus kembali ke shell "super" biasa tanpa insiden. Pasti ada jalan ~~
NB: Apa yang tidak saya tanyakan ...
- tidak bertanya di mana untuk mendapatkan halaman bash man
- tidak bertanya bagaimana membaca menginisialisasi perintah dari file ... Saya tahu bagaimana melakukan ini, itu bukan solusi yang saya cari
- tidak tertarik menggunakan layar tmux atau gnu
- tidak tertarik memberi konteks untuk ini. Yaitu, pertanyaannya dimaksudkan untuk bersifat umum, dan bukan untuk tujuan tertentu
- jika mungkin, saya ingin menghindari menggunakan solusi yang mencapai apa yang saya inginkan, tetapi dengan cara "kotor". Saya hanya ingin melakukan ini dalam satu baris. Secara khusus, saya tidak ingin melakukan sesuatu seperti
xterm -e 'ls'
exec bash
solusinya tidak cocok untuk Anda?exec bash
solusinya melibatkan dua subkulit yang terpisah. Saya ingin satu subkulit terus menerus.exec
adalah ia mengganti subshell pertama dengan yang kedua, jadi Anda hanya meninggalkan 1 shell di bawah induknya. Jika perintah inisialisasi Anda mengatur variabel lingkungan, mereka akan ada di shell yang dijalankan.exec
adalah Anda kehilangan apa pun yang tidak diturunkan ke subkulit melalui lingkungan, seperti variabel yang tidak diekspor, fungsi, alias, ...Jawaban:
Ini dapat dengan mudah dilakukan dengan pipa bernama sementara :
Penghargaan untuk jawaban ini diberikan untuk komentar dari Lie Ryan . Saya menemukan ini sangat berguna, dan kurang terlihat dalam komentar, jadi saya pikir itu harus menjadi jawabannya sendiri.
sumber
$HOME/.bashrc
itu tidak dieksekusi sekalipun. Itu harus dimasukkan dari pipa bernama sementara.bash --init-file <(echo ". \"$HOME/.bashrc\"; ls; pwd")
.
ini adalah sinonim untuksource
perintah: ss64.com/bash/source.html .sudo bash --init-file <(echo "ls; pwd")
atausudo -iu username bash --init-file <(echo "ls; pwd")
?Anda dapat melakukan ini secara tidak langsung dengan file temp, meskipun akan mengambil dua baris:
sumber
rm $BASH_SOURCE
.mktemp
memang memecahkan masalah file temp seperti yang ditunjukkan oleh @cjc. Bash dapat mendukung membaca perintah init dari stdin, tetapi sejauh yang saya tahu tidak. Specyfing-
sebagai file init dan memipainya setengah berfungsi, tetapi Bash kemudian keluar (mungkin karena mendeteksi pipa). Solusi elegan, IMHO, adalah menggunakan exec.Coba ini sebagai gantinya:
$SHELL
Itu membuat shell terbuka dalam mode interaktif, menunggu penutupanexit
.sumber
"Solusi yang diharapkan" yang saya maksudkan adalah pemrograman bash shell dengan bahasa pemrograman Expect :
Anda akan menjalankannya seperti:
./subshell.exp "ls; pwd"
sumber
Mengapa tidak menggunakan subshell asli?
Menutup perintah dengan tanda kurung menjadikan bash menelurkan subproses untuk menjalankan perintah ini, jadi Anda dapat, misalnya, mengubah lingkungan tanpa memengaruhi shell induk. Ini pada dasarnya lebih mudah dibaca setara dengan
bash -c "ls; pwd; exec $BASH"
.Jika itu masih terlihat verbose, ada dua opsi. Salah satunya adalah memiliki cuplikan ini sebagai fungsi:
Cara lain adalah membuat
exec $BASH
lebih pendek:Saya pribadi lebih suka
R
pendekatan, karena tidak perlu bermain dengan melarikan diri string.sumber
Jika
sudo -E bash
tidak berhasil, saya menggunakan yang berikut ini, yang sejauh ini telah memenuhi harapan saya:Saya mengatur HOME = $ HOME karena saya ingin sesi baru saya memiliki HOME yang diatur ke HOME pengguna saya, daripada HOME root, yang terjadi secara default pada beberapa sistem.
sumber
kurang elegan daripada
--init-file
, tapi mungkin lebih instrumental:sumber