我想运行远程 ssh 命令并让它们始终加载服务器端默认启动文件。我正在寻找一个解决方案才不是要求:
- 由 root 配置
- 每次向命令添加额外的样板
- 跨多个文件复制环境变量
我是不是希望将本地环境变量传输到远程 shell。我想使用普通ssh <host> <command>
语法运行远程命令并使用远程登录会话将获得相同的环境。
背景
为了简单起见,下面假设bash
使用
默认情况下,远程 ssh 命令启动非交互式、非登录 shell。引用手册页:
如果命令指定后,它会在远程主机上执行,而不是在登录 shell 上执行。
您可以通过运行以下命令在 shell 上更明确地看到这一点:
# the lack of 'i' indicates non-interactive
$ ssh localhost 'echo $-'
hBc
$ ssh localhost 'shopt login_shell'
login_shell off
但是,如果您的远程命令需要设置某些环境变量怎么办?作为非交互式、非登录 shell 意味着两者都不 .bash_profile
也.bashrc
不会被采购。
这是有问题的,例如,如果您使用类似的工具珀尔布鲁或者虚拟环境并希望在远程命令中使用您的自定义解释器:
$ which perl
/home/calid/perl5/perlbrew/perls/perl-5.20.1/bin/perl
$ ssh localhost 'which perl'
/usr/bin/perl
不满足上述要求的解决方案
在远程命令中显式调用登录 shell
$ ssh localhost 'bash --login -c "which perl"'
每次都需要额外的样板
在命令之前明确获取您的配置文件
$ ssh localhost 'source ~/.bash_profile && which perl'
每次都需要额外的样板
设置环境变量~/.ssh/environment
需要 root 才能在服务器上启用此功能
重复服务器启动文件中已设置的环境变量
设置ENV
和BASH_ENV
不起作用:.bash_profile
并且.bashrc
没有来源
设置~/.ssh/environment
有效,但需要 root 访问权限才能启用
在命令前面加上您需要的环境变量
每次都需要额外的样板(可能很多)
重复服务器启动文件中已设置的环境变量
相关文章
答案1
创建一个包装外壳函数,为您添加样板代码sshc
前缀:source ~/.bash_profile
function sshc {
local host=$1
local cmd=$2
ssh $host "source ~/.bash_profile && $cmd"
}
然后您可以将其用作:
$ sshc localhost 'which perl'
/home/calid/perl5/perlbrew/perls/perl-5.20.1/bin/perl
答案2
bash
~/.bashrc
即使在非交互式调用时也确实会读取,至少在 Debian 及其衍生ssh
版本#define SSH_SOURCE_BASHRC
上是这样(在我看来是一个错误功能,但在这里对您来说很方便)。
~/.bashrc
所以你可以添加到远程主机的顶部:
if [ -n "$SSH_CLIENT" ] &&
[ "$SHLVL" = 0 ] &&
[ -n "${-##*[il]*}" ]; then
. /etc/profile
. ~/.bash_profile
fi