How to invoke bash, run commands inside the new shell, and then give control back to user?
这一定很简单或者很复杂,但是我找不到任何关于它的东西…我试图打开一个新的bash实例,然后在其中运行一些命令,并将控制权交还给同一实例中的用户。
我试过:
1 | $ bash -lic"some_command" |
但这会在新实例中执行
还有一个可能影响答案的细节:如果我能让它工作,我会在我的
1 | bash --rcfile <(echo '. ~/.bashrc; some_command') |
分配创建临时文件。其他网站上的问题:
- https://serverfault.com/questions/368054/run-an-interactive-bash-subshell-with-initial-commands-without-return-to-the
- https://unix.stackexchange.com/questions/123103/how-to-keep-bash-running-after-command-execution
这是一个很晚的答案,但我有完全相同的问题,谷歌把我发送到这个页面,为了完整起见,这里是我如何解决这个问题的方法。
据我所知,bash没有选择去做最初海报想要做的事情。执行命令后,-c选项将始终返回。
破碎的解决方案:围绕这一点最简单和明显的尝试是:
1 | bash -c 'XXXX ; bash' |
这在一定程度上起作用(尽管有一个额外的子壳层)。但是,问题是,虽然子shell将继承导出的环境变量,但别名和函数不会继承。所以这可能对某些事情有用,但不是一般的解决方案。
更好的方法是动态创建一个启动文件并使用这个新的初始化文件调用bash,确保新的init文件在必要时调用常规的~/.bashrc。
1 2 3 4 5 6 7 8 9 10 | # 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 |
好的是,临时init文件一经使用就会自动删除,从而降低了未正确清理的风险。
注意:我不确定/etc/bashrc是否通常作为普通非登录shell的一部分被调用。如果是这样的话,您可能需要源代码/etc/bashrc以及您的~/.bashrc。
您可以将
编辑:因此,用
1 | more() { bash --rcfile ~/.more.sh ; } |
…在
根据Daveraja的回答,这里有一个bash脚本,可以解决这个问题。
如果您使用的是C-Shell并且您想要执行一个命令,那么考虑一种情况。不按如下方式离开C-Shell上下文/窗口,
要执行的命令:仅在*.h、*.c文件中递归搜索当前目录中的确切单词"testing"
1 | grep -nrs --color -w --include="*.{h,c}" Testing ./ |
解决方案1:从C-Shell进入bash并执行命令
1 2 3 | bash grep -nrs --color -w --include="*.{h,c}" Testing ./ exit |
解决方案2:将预期的命令写入文本文件并使用bash执行它
1 2 | echo 'grep -nrs --color -w --include="*.{h,c}" Testing ./' > tmp_file.txt bash tmp_file.txt |
解决方案3:使用bash在同一行上运行命令
1 | bash -c 'grep -nrs --color -w --include="*.{h,c}" Testing ./' |
解决方案4:创建一个sciprt(一次性)并将其用于将来的所有命令
1 2 | alias ebash './execute_command_on_bash.sh' ebash grep -nrs --color -w --include="*.{h,c}" Testing ./ |
剧本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #!/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 |
您可以通过源代码而不是运行脚本来获得所需的功能。如:
1 2 3 4 5 | $cat script cmd1 cmd2 $ . script $ at this point cmd1 and cmd2 have been run inside this shell |
在
1 2 3 4 5 6 | if ["$subshell" = 'true' ] then # commands to execute only on a subshell date fi alias sub='subshell=true bash' |
然后你可以用