Это должно быть очень просто или очень сложно, но я ничего не смог найти об этом ... Я пытаюсь открыть новый экземпляр bash, затем запустить в нем несколько команд и вернуть управление пользователю внутри этого тот же экземпляр .
Я старался:
$ bash -lic "some_command"
но это выполняется some_command
внутри нового экземпляра, а затем закрывает его. Я хочу, чтобы он оставался открытым.
Еще одна деталь, которая может повлиять на ответы: если я смогу заставить это работать, я буду использовать его в своих .bashrc
псевдонимах, так что бонусные баллы за alias
реализацию!
alias shortcut='bash -lic "some_command"'
моего .bashrc, затем запуститьshortcut
и получить новую оболочку, котораяsome_command
уже запущена в ней.Ответы:
bash --rcfile <(echo '. ~/.bashrc; some_command')
избавляет от создания временных файлов. Вопрос на других сайтах:
источник
The system cannot find the file specified.
cat ~/.bashrc
? 2) Работаетcat <(echo a)
? 3) Работаетbash --rcfile somefile
?bash.exe --rcfile ^<^(echo 'source $HOME/.bashrc; ls; pwd'^)
должен запускаться из командной строки Windows.sudo bash --init-file <(echo "ls; pwd")
илиsudo -iu username bash --init-file <(echo "ls; pwd")
?Это поздний ответ, но у меня была точно такая же проблема, и Google отправил меня на эту страницу, поэтому для полноты вот как я решил проблему.
Насколько я могу судить, у
bash
него нет возможности делать то, что хотел сделать исходный плакат.-c
Вариант всегда будет возвращаться после того , как команды были выполнены.Сломанное решение : простейшая и очевидная попытка обойти это:
bash -c 'XXXX ; bash'
Частично это работает (хотя и с дополнительным слоем подоболочки). Однако проблема заключается в том, что, хотя суб-оболочка наследует экспортируемые переменные среды, псевдонимы и функции не наследуются. Так что это может сработать для некоторых вещей, но не является общим решением.
Лучше : способ обойти это - динамически создать файл запуска и вызвать bash с этим новым файлом инициализации, убедившись, что ваш новый файл инициализации
~/.bashrc
при необходимости вызывает ваш обычный .# 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
Приятно то, что временный файл инициализации удаляется, как только он используется, что снижает риск того, что он не будет очищен правильно.
Примечание. Я не уверен, что / etc / bashrc обычно вызывается как часть обычной оболочки без входа в систему. Если это так, вы можете захотеть использовать источник / etc / bashrc, а также ваш
~/.bashrc
.источник
rm -f $TMPFILE
Вещь делает это. На самом деле я не помню вариант использования, который у меня был для этого, и теперь я использую более продвинутые методы автоматизации, но это правильный путь!bash --rcfile <(echo ". ~/.bashrc; a=b")
trap
.Вы можете передать
--rcfile
Bash, чтобы он прочитал файл по вашему выбору. Этот файл будет прочитан вместо вашего.bashrc
. (Если это проблема,~/.bashrc
используйте другой скрипт.)Изменить: Таким образом, функция для запуска новой оболочки с материалом
~/.more.sh
будет выглядеть примерно так:more() { bash --rcfile ~/.more.sh ; }
... и у
.more.sh
вас будут команды, которые вы хотите выполнить при запуске оболочки. (Я полагаю, было бы элегантно избежать отдельного файла запуска - вы не можете использовать стандартный ввод, потому что тогда оболочка не будет интерактивной, но вы можете создать файл запуска из документа здесь во временном месте, а затем прочитать его.)источник
Вы можете получить желаемую функциональность, взяв сценарий вместо его запуска. например:
источник
alias=''
файл?Добавьте в
~/.bashrc
такой раздел:if [ "$subshell" = 'true' ] then # commands to execute only on a subshell date fi alias sub='subshell=true bash'
Затем вы можете запустить подоболочку с помощью
sub
.источник
env subshell=true bash
(поскольку он не просочится$subshell
в последующие команды): Использование env против использования экспорта .env
. Для проверки того, определен он или нет, я используюecho $subshell
(вместо того,env | grep subshell
что используете вы).Принятый ответ действительно полезен! Просто добавлю, что подстановка процесса (т.е.
<(COMMAND)
) не поддерживается в некоторых оболочках (например,dash
).В моем случае я пытался создать настраиваемое действие (в основном однострочный сценарий оболочки) в файловом менеджере Thunar для запуска оболочки и активации выбранной виртуальной среды Python. Моя первая попытка была:
urxvt -e bash --rcfile <(echo ". $HOME/.bashrc; . %f/bin/activate;")
где
%f
- путь к виртуальной среде, обрабатываемой Thunar. Я получил ошибку (запустив Thunar из командной строки):/bin/sh: 1: Syntax error: "(" unexpected
Потом я понял, что мой
sh
(по сутиdash
) не поддерживает подмену процессов.Мое решение заключалось в том, чтобы вызвать
bash
на верхнем уровне интерпретацию подстановки процесса за счет дополнительного уровня оболочки:bash -c 'urxvt -e bash --rcfile <(echo "source $HOME/.bashrc; source %f/bin/activate;")'
В качестве альтернативы я попытался использовать здесь-документ,
dash
но безуспешно. Что-то типа:echo -e " <<EOF\n. $HOME/.bashrc; . %f/bin/activate;\nEOF\n" | xargs -0 urxvt -e bash --rcfile
PS: У меня недостаточно репутации, чтобы оставлять комментарии, модераторы, пожалуйста, не стесняйтесь переместить их в комментарии или удалить, если они не помогли с этим вопросом.
источник
В соответствии с ответом Давераджи , вот сценарий bash, который решит эту задачу.
Рассмотрим ситуацию, если вы используете C-shell и хотите выполнить команду, не выходя из контекста / окна C-shell следующим образом:
Выполняемая команда : искать точное слово Testing в текущем каталоге рекурсивно только в файлах * .h, * .c
grep -nrs --color -w --include="*.{h,c}" Testing ./
Решение 1. Войдите в bash из C-оболочки и выполните команду
bash grep -nrs --color -w --include="*.{h,c}" Testing ./ exit
Решение 2. Запишите предполагаемую команду в текстовый файл и выполните ее с помощью bash.
echo 'grep -nrs --color -w --include="*.{h,c}" Testing ./' > tmp_file.txt bash tmp_file.txt
Решение 3. Запустите команду в той же строке, используя bash
bash -c 'grep -nrs --color -w --include="*.{h,c}" Testing ./'
Решение 4. Создайте sciprt (одноразовый) и используйте его для всех будущих команд
alias ebash './execute_command_on_bash.sh' ebash grep -nrs --color -w --include="*.{h,c}" Testing ./
Сценарий выглядит следующим образом:
#!/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
источник
Вот еще один (рабочий) вариант:
Это открывает новый терминал gnome, а затем в новом терминале запускает bash. Сначала читается rc-файл пользователя, затем команда
ls -la
отправляется на выполнение в новую оболочку, прежде чем она станет интерактивной. Последнее эхо добавляет дополнительную строку новой строки, которая необходима для завершения выполнения.gnome-terminal -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'
Иногда я также считаю полезным украсить терминал, например, цветом для лучшей ориентации.
gnome-terminal --profile green -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'
источник
Выполнение команд в фоновой оболочке
Просто добавьте
&
в конец команды, например:источник
$ bash --init-file <(echo 'some_command') $ bash --rcfile <(echo 'some_command')
Если вы не можете или не хотите использовать подстановку процесса:
По-другому:
$ bash -c 'some_command; exec bash' $ sh -c 'some_command; exec sh'
sh
-only way (dash
,busybox
):источник
ENV=script
частью) была удалена или перефразирована, чтобы избежать путаницы с явной копипастой верхнего ответа.ENV
+sh
, присутствуют в других ответах, но в основном похоронены в тоннах текста или окружены ненужным / несущественным кодом. Я считаю, что краткое и ясное резюме принесет пользу всем.