Chcę uruchomić podpowłokę bash, (1) uruchomić kilka poleceń, (2), a następnie pozostać w tej podpowłoce, aby zrobić tak, jak mi się podoba. Mogę wykonać każdą z tych czynności indywidualnie:
Uruchom polecenie za pomocą
-c
flagi:$> bash -c "ls; pwd; <other commands...>"
jednak natychmiast powraca do „super” powłoki po wykonaniu poleceń. Mogę również uruchomić interaktywną podpowłokę:
Rozpocznij nowy
bash
proces:$> bash
i nie opuści podpowłoki, dopóki nie powiem tak wyraźnie ... ale nie mogę uruchomić żadnych początkowych poleceń. Najbliższym rozwiązaniem, jakie znalazłem, jest:
$> bash -c "ls; pwd; <other commands>; exec bash"
co działa, ale nie tak, jak chciałem, ponieważ uruchamia podane polecenia w jednej podpowłoce, a następnie otwiera osobne dla interakcji.
Chcę to zrobić w jednym wierszu. Po wyjściu z podpowłoki powinienem wrócić do zwykłej „super” powłoki bez żadnych incydentów. Musi być jakiś sposób ~~
NB: O co nie pytam ...
- nie pytając, skąd wziąć stronę podręcznika bash
- nie pytam, jak czytać polecenia inicjujące z pliku ... Wiem jak to zrobić, to nie jest rozwiązanie, którego szukam
- nie jestem zainteresowany używaniem ekranu tmux lub gnu
- nie zainteresowany nadaniem kontekstu temu. Tj. Pytanie ma być ogólne, a nie w żadnym konkretnym celu
- jeśli to możliwe, chcę uniknąć stosowania obejść, które pozwalają osiągnąć to, czego chcę, ale w „brudny” sposób. Chcę to zrobić tylko w jednej linii. W szczególności nie chcę robić czegoś takiego
xterm -e 'ls'
exec bash
rozwiązanie jest dla Ciebie nieodpowiednie?exec bash
rozwiązanie obejmuje dwa oddzielne podpowłok. Chcę jedną ciągłą podpowłokę.exec
polega na tym, że zastępuje pierwszą podpowłokę drugą, więc pozostała tylko 1 powłoka poniżej rodzica. Jeśli komendy inicjujące ustawiają zmienne środowiskowe, będą one istnieć w wykonanej powłoce.exec
polega na tym, że tracisz wszystko, co nie jest przekazywane do podpowłoki przez środowisko, takie jak nieeksportowane zmienne, funkcje, aliasy, ...Odpowiedzi:
Można to łatwo zrobić za pomocą tymczasowych nazwanych potoków :
Podziękowania dla tej odpowiedzi należą do komentarza Lie Ryan . Uznałem to za bardzo przydatne i jest mniej zauważalne w komentarzach, więc pomyślałem, że powinna to być własna odpowiedź.
źródło
$HOME/.bashrc
to jednak, że nie jest wykonywany. Musiałby być dołączony z tymczasowej nazwy potoku.bash --init-file <(echo ". \"$HOME/.bashrc\"; ls; pwd")
.
jest synonimemsource
polecenia: ss64.com/bash/source.html .sudo bash --init-file <(echo "ls; pwd")
lubsudo -iu username bash --init-file <(echo "ls; pwd")
?Możesz to zrobić na okrągło z plikiem tymczasowym, chociaż zajmie to dwie linie:
źródło
rm $BASH_SOURCE
go.mktemp
rozwiązanie problemu z plikiem tymczasowym, jak wskazał @cjc. Bash mógłby wesprzeć czytanie komend inicjujących ze standardowego wejścia, ale o ile wiem, że nie. Określanie-
jako plik init i przesyłanie ich do potoku w połowie działa, ale Bash następnie kończy działanie (prawdopodobnie dlatego, że wykrył potok). Eleganckim rozwiązaniem IMHO jest użycie exec.Spróbuj zamiast tego:
$SHELL
Powoduje, że powłoka jest otwarta w trybie interaktywnym, czekając na zamknięcieexit
.źródło
„Oczekiwane rozwiązanie”, o którym mówiłem, to programowanie powłoki bash za pomocą języka programowania Expect :
Urodziłbyś się tak:
./subshell.exp "ls; pwd"
źródło
Dlaczego nie użyć natywnych podpowłok?
Dołączenie poleceń w nawiasach powoduje, że bash spawn jest procesem podrzędnym do uruchamiania tych poleceń, dzięki czemu można na przykład zmieniać środowisko bez wpływu na powłokę nadrzędną. Jest to w zasadzie bardziej czytelny odpowiednik
bash -c "ls; pwd; exec $BASH"
.Jeśli nadal wygląda to na pełne, istnieją dwie opcje. Jednym z nich jest posiadanie tego fragmentu jako funkcji:
Innym jest
exec $BASH
skrócenie:Osobiście
R
bardziej podoba mi się podejście, ponieważ nie trzeba bawić się uciekającymi strunami.źródło
Jeśli
sudo -E bash
nie działa, korzystam z następujących, które do tej pory spełniły moje oczekiwania:Ustawiam HOME = $ HOME, ponieważ chcę, aby moja nowa sesja miała HOME ustawiony na HOME mojego użytkownika, a nie na HOME, co dzieje się domyślnie w niektórych systemach.
źródło
mniej elegancki niż
--init-file
, ale może bardziej instrumentalny:źródło