To musi być albo bardzo proste, albo bardzo złożone, ale nie mogłem nic na ten temat znaleźć ... Próbuję otworzyć nową instancję basha, następnie uruchomić w niej kilka poleceń i oddać kontrolę użytkownikowi znajdującemu się w niej ta sama instancja .
Próbowałem:
$ bash -lic "some_command"
ale to jest wykonywane some_command
wewnątrz nowej instancji, a następnie ją zamyka. Chcę, żeby było otwarte.
Jeszcze jeden szczegół, który może mieć wpływ na odpowiedzi: jeśli uda mi się to uruchomić, użyję go .bashrc
jako aliasu (aliasów), więc dodatkowe punkty za alias
wdrożenie!
alias shortcut='bash -lic "some_command"'
w moim .bashrc, a następnie uruchomićshortcut
i mieć nową powłokę zsome_command
już uruchomioną.Odpowiedzi:
bash --rcfile <(echo '. ~/.bashrc; some_command')
rezygnuje z tworzenia plików tymczasowych. Pytanie w innych witrynach:
źródło
The system cannot find the file specified.
cat ~/.bashrc
działa? 2) Czycat <(echo a)
działa? 3) Czybash --rcfile somefile
działa?bash.exe --rcfile ^<^(echo 'source $HOME/.bashrc; ls; pwd'^)
powinna być uruchamiana z wiersza poleceń systemu Windows.sudo bash --init-file <(echo "ls; pwd")
lubsudo -iu username bash --init-file <(echo "ls; pwd")
?To jest późna odpowiedź, ale miałem dokładnie ten sam problem i Google wysłał mnie na tę stronę, więc aby uzyskać kompletność, oto jak poradziłem sobie z problemem.
O ile wiem,
bash
nie ma możliwości zrobienia tego, co chciał zrobić oryginalny plakat.-c
Opcja będzie zawsze wrócić po rozkazy zostały wykonane.Zepsute rozwiązanie : Najprostsza i oczywista próba obejścia tego:
bash -c 'XXXX ; bash'
To częściowo działa (aczkolwiek z dodatkową warstwą podpowłoki). Jednak problem polega na tym, że podczas gdy powłoka podrzędna odziedziczy wyeksportowane zmienne środowiskowe, aliasy i funkcje nie są dziedziczone. Może to działać w niektórych przypadkach, ale nie jest ogólnym rozwiązaniem.
Lepiej : sposobem na obejście tego jest dynamiczne utworzenie pliku startowego i wywołanie bash z tym nowym plikiem inicjalizacyjnym, upewniając się, że nowy plik init wywołuje zwykły plik,
~/.bashrc
jeśli to konieczne.# Create a temporary file TMPFILE=$(mktemp) # Add stuff to the temporary file echo "source ~/.bashrc" > $TMPFILE echo "<other commands>" >> $TMPFILE echo "rm -f $TMPFILE" >> $TMPFILE # Start the new bash shell bash --rcfile $TMPFILE
Fajną rzeczą jest to, że tymczasowy plik init usunie się, gdy tylko zostanie użyty, zmniejszając ryzyko, że nie zostanie poprawnie wyczyszczony.
Uwaga: nie jestem pewien, czy / etc / bashrc jest zwykle wywoływany jako część normalnej powłoki niezalogowanej. Jeśli tak, możesz chcieć pobrać / etc / bashrc, a także swój
~/.bashrc
.źródło
rm -f $TMPFILE
Co czyni go. Właściwie nie pamiętam przypadku użycia, który miałem do tego, a teraz używam bardziej zaawansowanych technik automatyzacji, ale to jest droga!bash --rcfile <(echo ". ~/.bashrc; a=b")
trap
.Możesz przekazać
--rcfile
Bashowi, aby odczytał wybrany plik. Ten plik zostanie odczytany zamiast twojego.bashrc
. (Jeśli to problem, źródło~/.bashrc
z innego skryptu).Edycja: Tak więc funkcja uruchamiająca nową powłokę z rzeczami
~/.more.sh
wyglądałaby mniej więcej tak:more() { bash --rcfile ~/.more.sh ; }
... aw
.more.sh
tobie byłyby polecenia, które chcesz wykonać podczas uruchamiania powłoki. (Przypuszczam, że elegancko byłoby uniknąć oddzielnego pliku startowego - nie można używać standardowego wejścia, ponieważ wtedy powłoka nie będzie interaktywna, ale można utworzyć plik startowy z dokumentu tutaj w tymczasowej lokalizacji, a następnie przeczytać go.)źródło
Możesz uzyskać żądaną funkcjonalność, pozyskując skrypt zamiast go uruchamiać. na przykład:
źródło
alias=''
?Dołącz do
~/.bashrc
sekcji takiej jak ta:if [ "$subshell" = 'true' ] then # commands to execute only on a subshell date fi alias sub='subshell=true bash'
Następnie możesz rozpocząć podpowłokę za pomocą
sub
.źródło
env subshell=true bash
(ponieważ nie wycieknie to$subshell
do kolejnych poleceń): Używanie env vs. używanie eksportu .env
. Aby sprawdzić, czy jest zdefiniowany, czy nie, używamecho $subshell
(zamiastenv | grep subshell
tego używasz).Przyjęta odpowiedź jest naprawdę pomocna! Wystarczy dodać, że podstawianie procesów (tj.
<(COMMAND)
) Nie jest obsługiwane w niektórych powłokach (npdash
.).W moim przypadku próbowałem utworzyć niestandardową akcję (w zasadzie jednoliniowy skrypt powłoki) w menedżerze plików Thunar, aby uruchomić powłokę i aktywować wybrane środowisko wirtualne Pythona. Moja pierwsza próba to:
urxvt -e bash --rcfile <(echo ". $HOME/.bashrc; . %f/bin/activate;")
gdzie
%f
jest ścieżka do wirtualnego środowiska obsługiwanego przez Thunara. Otrzymałem błąd (uruchamiając Thunara z linii poleceń):/bin/sh: 1: Syntax error: "(" unexpected
Wtedy zdałem sobie sprawę, że mój
sh
(zasadniczodash
) nie obsługuje zastępowania procesów.Moim rozwiązaniem było wywołanie
bash
na najwyższym poziomie w celu zinterpretowania podstawienia procesu kosztem dodatkowego poziomu powłoki:bash -c 'urxvt -e bash --rcfile <(echo "source $HOME/.bashrc; source %f/bin/activate;")'
Alternatywnie, próbowałem użyć dokumentu tutaj,
dash
ale bez powodzenia. Coś jak:echo -e " <<EOF\n. $HOME/.bashrc; . %f/bin/activate;\nEOF\n" | xargs -0 urxvt -e bash --rcfile
PS: Nie mam wystarczającej reputacji, aby publikować komentarze, moderatorzy mogą swobodnie przenosić to do komentarzy lub usuwać, jeśli nie jest to pomocne w przypadku tego pytania.
źródło
Zgodnie z odpowiedzią daveraja , oto skrypt bash, który rozwiąże cel.
Rozważ sytuację, jeśli używasz powłoki C i chcesz wykonać polecenie bez opuszczania kontekstu / okna powłoki C w następujący sposób:
Polecenie do wykonania : Wyszukaj rekurencyjnie dokładnie słowo „Testing” w bieżącym katalogu tylko w plikach * .h, * .c
grep -nrs --color -w --include="*.{h,c}" Testing ./
Rozwiązanie 1 : Wejdź do bash z powłoki C i wykonaj polecenie
bash grep -nrs --color -w --include="*.{h,c}" Testing ./ exit
Rozwiązanie 2 : Zapisz żądane polecenie w pliku tekstowym i wykonaj je za pomocą basha
echo 'grep -nrs --color -w --include="*.{h,c}" Testing ./' > tmp_file.txt bash tmp_file.txt
Rozwiązanie 3 : Uruchom polecenie w tej samej linii, używając bash
bash -c 'grep -nrs --color -w --include="*.{h,c}" Testing ./'
Rozwiązanie 4 : Utwórz sciprt (jednorazowo) i używaj go do wszystkich przyszłych poleceń
alias ebash './execute_command_on_bash.sh' ebash grep -nrs --color -w --include="*.{h,c}" Testing ./
Scenariusz jest następujący,
#!/bin/bash # ========================================================================= # References: # https://stackoverflow.com/a/13343457/5409274 # https://stackoverflow.com/a/26733366/5409274 # https://stackoverflow.com/a/2853811/5409274 # https://stackoverflow.com/a/2853811/5409274 # https://www.linuxquestions.org/questions/other-%2Anix-55/how-can-i-run-a-command-on-another-shell-without-changing-the-current-shell-794580/ # https://www.tldp.org/LDP/abs/html/internalvariables.html # https://stackoverflow.com/a/4277753/5409274 # ========================================================================= # Enable following line to see the script commands # getting printing along with their execution. This will help for debugging. #set -o verbose E_BADARGS=85 if [ ! -n "$1" ] then echo "Usage: `basename $0` grep -nrs --color -w --include=\"*.{h,c}\" Testing ." echo "Usage: `basename $0` find . -name \"*.txt\"" exit $E_BADARGS fi # Create a temporary file TMPFILE=$(mktemp) # Add stuff to the temporary file #echo "echo Hello World...." >> $TMPFILE #initialize the variable that will contain the whole argument string argList="" #iterate on each argument for arg in "$@" do #if an argument contains a white space, enclose it in double quotes and append to the list #otherwise simply append the argument to the list if echo $arg | grep -q " "; then argList="$argList \"$arg\"" else argList="$argList $arg" fi done #remove a possible trailing space at the beginning of the list argList=$(echo $argList | sed 's/^ *//') # Echoing the command to be executed to tmp file echo "$argList" >> $TMPFILE # Note: This should be your last command # Important last command which deletes the tmp file last_command="rm -f $TMPFILE" echo "$last_command" >> $TMPFILE #echo "---------------------------------------------" #echo "TMPFILE is $TMPFILE as follows" #cat $TMPFILE #echo "---------------------------------------------" check_for_last_line=$(tail -n 1 $TMPFILE | grep -o "$last_command") #echo $check_for_last_line #if tail -n 1 $TMPFILE | grep -o "$last_command" if [ "$check_for_last_line" == "$last_command" ] then #echo "Okay..." bash $TMPFILE exit 0 else echo "Something is wrong" echo "Last command in your tmp file should be removing itself" echo "Aborting the process" exit 1 fi
źródło
Oto kolejny (działający) wariant:
Spowoduje to otwarcie nowego terminala gnome, a następnie w nowym terminalu uruchomi bash. Najpierw odczytywany jest plik rc użytkownika, a następnie polecenie
ls -la
jest wysyłane do wykonania do nowej powłoki, zanim stanie się interaktywna. Ostatnie echo dodaje dodatkowy znak nowej linii, który jest potrzebny do zakończenia wykonywania.gnome-terminal -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'
Przydaje mi się też czasem udekorowanie terminala, np. Kolorem dla lepszej orientacji.
gnome-terminal --profile green -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'
źródło
Wykonywanie poleceń w powłoce w tle
Wystarczy dopisać
&
na końcu polecenia np:źródło
$ bash --init-file <(echo 'some_command') $ bash --rcfile <(echo 'some_command')
Jeśli nie możesz lub nie chcesz korzystać z zastępowania procesów:
Inny sposób:
$ bash -c 'some_command; exec bash' $ sh -c 'some_command; exec sh'
sh
-tylko sposób (dash
,busybox
):źródło
ENV=script
usunięcie lub przeformułowanie górnej sekcji (przed częścią), aby uniknąć pomylenia z rażącym kopiowaniem i wklejaniem pierwszej odpowiedzi.ENV
+sh
jeden są obecne w innych odpowiedziach, ale przeważnie są ukryte w tonach tekstu lub otoczone niepotrzebnym / nieistotnym kodem. Uważam, że krótkie, jasne podsumowanie byłoby korzystne dla wszystkich.