我想为工作区配置制作一个脚本,我需要它来打开ssh终端,在里面我需要抛出一个bash命令(因为默认为tcsh),在bash上抛出另一个命令,我希望终端保持在最后一个状态。
我在脚本中有这个:
...
cd xxx/xxx
bash
source setup.sh
...
exit 0
当脚本结束时,我的终端会停留在bash中,但不会执行接下来的步骤。
我也试过这个:
ssh -X URL << '___'
cd xxx/xxx
bash -c "source setup.sh"
___
如果我只在ssh URL内启动bash -c
,它会起作用,但如果我完成了,它会结束执行并将我从ssh URL外删除。如果我在最后做CCD_ 2;bash:在这个shell中没有作业控制&;把我甩了。-exec
选项也执行同样的操作。
我该如何正确地执行此操作?
您可以在标准输入上将任意复杂的脚本传递给bash
。
bash <<'____'
source setup.sh
: things
# no explicit exit really needed
____
将"#!/bin/bash"放在"setup.sh".的头上
这将使该脚本在Bash shell下运行。
我要做的是将位于bash
行和exit 0
之间的命令放入一个单独的文件中,例如mycommands.sh
#!/bin/bash
source setup.sh
...
exit 0
chmod +x mycommands.sh
然后调用mycommands.sh在你写bash 的时候
但你也可以
bash -c "source setup.sh; ... ; exit 0"
后退一步&构建最终答案(fwiw由于人为的(尽管极为常见的)行政/管理限制,所述问题似乎不必要地复杂,因此重新定义问题可能会提供更容易的解决方案):
首先,可以通过使用chsh -s /bin/bash
(或指向首选bash
的任何路径,例如/opt/local/bin/bash
)更改远程主机上的默认shell(不带root),并根据需要将启动命令放入~/.bash_login
或~/.bashrc
(用谷歌搜索优先规则,但需要注意的是:在bash+OS的不同版本中,你可能会看到不同的行为,所以请进行测试;也许今天这不是什么问题,但特别是macOS和旧的Unix(Solaris)在过去给我带来了问题。)如果你真的有root访问权限,只需使用usermod
来更改远程设备上的默认shell(但如果是这样的话,这个问题就没有意义了。)
按照同样的思路,将ssh
放入远程并启动交互式bash
会话,使用bash -l
将导致为登录shell运行init脚本(例如~/.bash_login
、~/.bash_profile
、~/.bashrc,再次检查规则的优先级、默认值和回退)
$ ssh -t user@host '/path/to/foo.sh; bash -l'
但请注意,在bash -l
之前导致env更改的任何命令都不会出现在您的shell中。除非它们在远程init文件(~/.bashrc
等)中。
因此,最后,您可以在bash -i
0命令中指定init文件,而不是在远程上运行默认的init文件,以便设置远程env,将这些更改保留在bash
shell中:
$ ssh -t user@host 'bash --init-file ~/my_env.sh'
其中CCD_ 22替换您的CCD_ 23(或其他)。如果您还希望~/.bashrc
运行,只需";包括";(又称"源"),它位于my_env.sh文件(即:. ~/.bashrc
)中。
最后,如果~/my_env.sh
文件实际上不在远程,您可以通过进程替换传递任意命令(动态生成init文件):
$ ssh -t user@host 'bash --init-file <(echo "export FOO=bar; source /path/foo.env")'
然而,由于语法<( commands )
特定于bash
,您需要在默认的远程shell中使用类似的语法,或者在bash中运行命令(在转义引号时出现了一个有趣的问题):
$ ssh -t user@host 'bash -c "bash --init-file <(echo "export FOO=bar; source /path/foo.env")"'
此时,您已登录到远程,远程bash
shell正在运行,FOO
应为bar
,并且远程/path/foo.env
在当前shell中仍然有效。(可以选择远程~/.bashrc
的来源,但要小心可能不起作用的奇怪事情,例如花哨的提示PS1
的东西,但我跑题了。)