Я хочу запустить оболочку bash, (1) выполнить несколько команд, (2) и затем остаться в этой оболочке, чтобы выполнить, как мне нравится. Я могу сделать каждый из них в отдельности:
Запустите команду, используя
-c
флаг:$> bash -c "ls; pwd; <other commands...>"
однако он сразу возвращается в «супер» оболочку после выполнения команд. Я также могу просто запустить интерактивную подоболочку:
Начать новый
bash
процесс:$> bash
и он не выйдет из подоболочки, пока я не скажу об этом явно ... но я не могу выполнить какие-либо начальные команды. Ближайшее решение, которое я нашел, это:
$> bash -c "ls; pwd; <other commands>; exec bash"
который работает, но не так, как я хотел, так как он запускает данные команды в одной подоболочке, а затем открывает отдельную для взаимодействия.
Я хочу сделать это в одной строке. После выхода из подоболочки я должен вернуться к обычной «супер» оболочке без происшествий. Должен быть способ ~~
NB: что я не спрашиваю ...
- не спрашивая, где взять man-страницу bash
- не спрашиваю, как читать команды инициализации из файла ... я знаю, как это сделать, это не решение, которое я ищу
- не заинтересованы в использовании экрана tmux или gnu
- не заинтересованы в предоставлении контекста для этого. Т.е. вопрос должен быть общим, а не для какой-то конкретной цели
- если возможно, я хочу избегать использования обходных путей, которые выполняют то, что я хочу, но «грязным» способом. Я просто хочу сделать это в одной строке. В частности, я не хочу делать что-то вроде
xterm -e 'ls'
exec bash
решение вам не подходит?exec bash
решение включает в себя две отдельные подоболочки. Я хочу одну сплошную подоболочку.exec
том, что он заменяет первый подоболочек вторым, поэтому вы оставляете только одну оболочку ниже родительского. Если ваши команды инициализации устанавливают переменные окружения, они будут существовать в исполняемой оболочке.exec
том, что вы теряете все, что не передается в субоболочки через окружение, такие как неэкспортируемые переменные, функции, псевдонимы, ...Ответы:
Это можно легко сделать с помощью временных именованных каналов :
Кредит на этот ответ идет на комментарий от Ли Райана . Я нашел это действительно полезным, и это менее заметно в комментариях, поэтому я подумал, что это должен быть собственный ответ.
источник
$HOME/.bashrc
это не выполняется, хотя. Это должно быть включено из временного именованного канала.bash --init-file <(echo ". \"$HOME/.bashrc\"; ls; pwd")
.
это синонимsource
команды: ss64.com/bash/source.html .sudo bash --init-file <(echo "ls; pwd")
илиsudo -iu username bash --init-file <(echo "ls; pwd")
?Вы можете сделать это окольным путем с временным файлом, хотя это займет две строки:
источник
rm $BASH_SOURCE
в него.mktemp
он решает проблему временного файла, как указал @cjc. Bash может поддерживать чтение команд init из stdin, но, насколько я могу судить, этого не делает. Указание в-
качестве файла инициализации и передача их наполовину работает, но затем Bash завершает работу (возможно, потому, что обнаружил конвейер). ИМХО элегантным решением является использование exec.Попробуйте это вместо этого:
$SHELL
Это делает оболочку открытой в интерактивном режиме, ожидая закрытия сexit
.источник
«Решение Expect», о котором я говорил, - это программирование оболочки bash на языке программирования Expect :
Вы бы запустили это как:
./subshell.exp "ls; pwd"
источник
Почему бы не использовать родные подоболочки?
Заключение команд в круглые скобки делает bash spawn подпроцессом для выполнения этих команд, так что вы можете, например, изменять среду, не затрагивая родительскую оболочку. Это в основном более читаемый эквивалент
bash -c "ls; pwd; exec $BASH"
.Если это все еще выглядит многословно, есть два варианта. Одним из них является использование этого фрагмента в качестве функции:
Другое сделать
exec $BASH
корочеЛично мне
R
больше нравится подход, так как нет необходимости играть с выходящими струнами.источник
Если
sudo -E bash
не работает, я использую следующее, которое оправдало мои ожидания:Я установил HOME = $ HOME, потому что я хочу, чтобы в моем новом сеансе HOME было установлено значение HOME моего пользователя, а не HOME root, что происходит по умолчанию в некоторых системах.
источник
менее элегантный
--init-file
, но, возможно, более удобный:источник