启动新的 bash 会话背景

启动新的 bash 会话背景

是否可以创建一个名为 的命令new_bash来允许我执行以下操作?

new_bash alias test="ls"
new bash alias new_command="ls"

new_bash test
file1
new_bash new_command
file1

答案1

##Background:

cd $(mktemp -d)
> file1

##Setup state (background bash + pipe)
pipeDir=$(mktemp -d)
mkfifo $pipeDir/p #pipe for communicating with the shell
#start the shell in the background, make it read from the pipe, and disable I/O buffering
stdbuf -i0 -o0 bash < $pipeDir/p & 
#open the pipe from the other end on fd 3 (or another fd)
exec 3>$pipeDir/p && 
rm -rf "$pipeDir" #don't need the directory or the physical link to the pipe anymore

##Now you can communicate with the shell
echo ls >&3
#Ouptuts: file1

#This is how you end it all
exec 3>&-

您的函数需要维护全局状态。您的函数需要检查状态是否已设置,如果尚未设置则进行设置(也许通过检查变量是否存在)。设置完成后或者如果状态存在,它只需要echo其参数 ( "$@")&3或您打开管道的任何文件描述符。

制作三个函数可能是一个更好的主意(这会更高效):

init_new_bash
new_bash
end_new_bash

示例(需要更好的信号处理):

#!/bin/sh 
#^will work in bash also
init_new_bash(){
    set -e #all must succeed
    pipeDir=$(mktemp -d)  
    mkfifo "$pipeDir/p" 

    stdbuf -i0 -o0 bash < "$pipeDir"/p & 
    bashPid=$! 

    exec 3>"$pipeDir/p"
    rm -rf "$pipeDir" 
    set +e
}
new_bash(){ echo "$@" >&3; }
end_new_bash(){ exec 3>&-; wait "$bashPid"; }

##Test run:
init_new_bash && {

   new_bash echo hello world
   new_bash ls

end_new_bash;}

答案2

你所问的看起来与一个简单的非常相似子外壳

每当您使用括号封装命令时,例如(ls),该命令将在当前 shell 的子进程中运行。

对于你的例子:

( 
alias test='ls'
alias new_command='ls'
test
new_command
)

或者,由于别名被复制到子 shell

alias test='ls'
alias new_command='ls'
( test ) # one subshell
( new_command ) # another subshell

如果你需要你的命令在同一个子shell中运行:

alias test='ls'
alias new_command='ls'
( test ; new_command ) # same subshell

相关内容