通过ssh启动文件


10

在启动任何sh shell之前,我需要执行一些重要命令。这是在SSH命令(ssh host somecommand)和其他运行命令的程序中传递SSH命令所必需的。

在我.profile有这个:

ihammerhands@wreckcreations:~> cat .profile
#specific environment and startup programs
export PS1="\u@wreckcreations:\w> "
export PYTHONPATH=~/python/lib/python2.4/site-packages
export PATH=$PATH:~/bin:~/python/bin

但是,这失败了:

W:\programming\wreckcreations-site\test-hg>ssh name@host echo $PATH
Enter passphrase for key '/home/Owner/.ssh/id_rsa':
/usr/local/bin:/bin:/usr/bin

注意缺少的PATH选项

sh配置文件的专有名称是什么?注意:我没有root访问权限,并且不希望将此权限应用于其他用户。还有另一种方法吗?


编辑:似乎/bin/sh链接到bash,这并不奇怪。令人惊讶的是,我的个人资料仍然被忽略。有什么建议?


1
我不想重复手册页中的内容,因此只需在bash手册页中的“ INVOCATION”部分下查找即可。它在顶部附近,描述您需要了解的所有信息。
卡姆(Camh)2010年

您可以尝试使用ssh name@host -t echo $PATH
Gert 2010年

@Gert输出相同
TheLQ 2010年

@camh如果我还没有检查手册页,您认为我会问这个问题吗?我已经阅读了很多遍+其他文章,但始终找不到该特定问题的答案,因为我不确定在哪个阶段执行ssh命令和其他程序的命令
TheLQ 2010年

1
@TheLQ:我不认识您,所以不知道您是否可以查看手册页。我所知道的只是答案就在那里,所以我没有一字接一字地重复,而是指出了它。一个更具体的指针是查找非交互式shell,因为这就是您的ssh场景。如果手册页中的内容不清楚,则可以提出更具体的问题。
camh 2010年

Answers:


8

似乎值得注意的是,您在问题中提到的命令

ssh name@host echo $PATH

几乎永远不会有用。$ PATH的变量替换由您的本地shell完成,并传递给ssh,后者在远程系统上执行echo以打印path变量的内容,因为它在本地系统上扩展了。这是我在Mac和网络上的Linux计算机之间执行类似操作的示例:

LibMBP:~ will$ echo $PATH
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren echo $PATH
will@warren's password: 
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren 'echo $PATH'
will@warren's password: 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
LibMBP:~ will$ 

请注意,我需要如何使用引号来防止本地shell扩展变量。


在Windows Cygwin域中,单引号在Cygwin或Command提示符下不起作用。奇怪的是,双引号使PATH完全扩展到我在Cygwin中的本地计算机。所以ssh给我的东西不是我的路,而是服务器的路
TheLQ

@TheLQ在UNIX提示符下(包括Cygwin),单引号是必需的,但是在cmd提示符下不需要任何引号。
吉尔(Gilles)“所以,别再邪恶了”

12

~/.profile仅由登录shell执行。调用该shell的程序确定该shell是否将是登录shell(通过-在shell调用上放置第0个参数的第一个字符作为a )。登录以执行特定命令时,通常不会执行该命令。

仅当您不指定命令时,OpenSSH才会调用登录Shell。因此,如果您指定命令,~/.profile将不会被读取。

OpenSSH允许在服务器端设置环境变量。必须在服务器配置中使用PermitUserEnvironment指令启用此功能。可以在文件中设置变量~/.ssh/environment。假设您使用公共密钥身份验证,还可以在相关行的开头的~/.ssh/authorized_keys:add environment="FOO=bar"中设置每个密钥的变量。

Ssh还支持发送环境变量。在OpenSSH中,使用中的SendEnv指令~/.ssh/config。但是,必须AcceptEnv在服务器配置中使用指令启用特定的环境变量,因此这可能对您不可行。

只要您使用公钥身份验证,我认为一件事总是可以做的(很奇怪)是(滥用)文件中的command=选项authorized_keys。带command选项的键仅适用于运行指定的命令。但是authorized_keys文件中的命令在环境变量SSH_ORIGINAL_COMMAND设置为用户指定的命令的情况下运行。如果用户未指定命令,因此需要交互式外壳程序,则此变量为空。因此,您可以在其中使用类似的内容~/.ssh/authorized_keys(当然,如果您不使用此密钥进行身份验证,那么它将不适用):

command=". ~/.profile; if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then eval \"$SSH_ORIGINAL_COMMAND\"; else exec \"$SHELL\"; fi" ssh-rsa 

另一种可能性是在服务器上编写包装器脚本。类似于以下内容~/bin/ssh-wrapper

#!/bin/sh
. ~/.profile
exec "${0##*/}" "$@"

然后建立指向该脚本的符号链接,称为rsyncunison等等--rsync-path='bin/rsync'。在rsync命令行上传递,以此类推。另外,有些命令允许您指定整个shell片段以远程运行,这使您可以使命令自包含:例如,对于rsync,可以使用--rsync-path='. ~/.profile; rsync'

还有另一种方法,这取决于您的登录shell是bash还是zsh。Bash总是~/.bashrc在rshd或sshd调用时读取,即使它不是交互式的(但如果调用为sh)也不是。Zsh总是读取~/.zshenv

## ~/.bashrc
if [[ $- != *i* ]]; then
  # Either .bashrc was sourced explicitly, or this is an rsh/ssh session.
  . ~/.profile
fi

## ~/.zshenv
if [[ $(ps -p $PPID -o comm=) = [rs]shd && $- != *l* ]]; then
  # Not a login shell, but this is an rsh/ssh session
  . ~/.profile
fi

那其他命令执行的命令呢?在这种情况下,它将是Mercurial挂钩。Mercurial需要走上钩,甚至想起工作的
必要

使用我指示的任何技术来使您的概要文件在非交互式ssh命令中运行。(command=中的authorized_keys)其中一个透明地工作。其他的则需要在ssh服务器配置中使用特定的shell或选项。的Mercurial等价物--rsync-path--remotecmd
吉尔(Gilles)“所以,别再邪恶了”

对于某些人来说,包含与command=发布后的完整命令相同的完整命令可能是有用的superuser.com/a/207262/137762
mforbes 2013年


0

我没有时间来测试这一点,但仔细查看我发现的手册页:

man bash:例如,以非交互方式启动bash时,要运行shell脚本,它将在环境中查找变量BASH_ENV,将其值扩展到环境中,然后将扩展后的值用作要删除的文件的名称。读取并执行。Bash的行为就像执行以下命令一样:if [-n“ $ BASH_ENV”]; 然后 。“ $ BASH_ENV”; fi,但PATH变量的值不用于搜索文件名。

man ssh:〜/ .ssh / environment包含环境变量的其他定义;请参阅上面的环境。

该组合建议您如何使ssh执行.profile

不幸的是,我的服务器的PermitUserEnvironment的默认值为no,这对我来说不起作用(就像我说的,我没有时间再玩了)。


即使我可以通过在环境中明确声明一些环境变量来使SSH正常工作,当其他程序调用命令时,它仍然无法解决使我的配置文件执行的问题
TheLQ 2010年

在您的示例中,您要做的只是设置环境变量,您还想做什么?
kasterma 2010年

0

(已删除...作为新用户只能有一个超链接〜)

更新资料

抱歉,我没有看到这与非交互式会话有关,上面的链接不适用于该会话。

当Bash在SH兼容模式下启动时,它将尝试尽可能接近于sh的历史版本的启动行为,同时也要符合POSIX®标准。如果是登录shell,则读取的配置文件为/ etc / profile和〜/ .profile。

如果不是登录外壳,则将评估环境变量ENV,并将所得文件名用作启动文件的名称。

读取启动文件后,Bash进入POSIX(r)兼容模式(用于运行,而不用于启动!)。

Bash在以下情况下以sh兼容模式启动:

  • argv [0]中的基本文件名是sh(:! :!:)

所以问题是,即使您的shell这样启动,它为什么也不执行它。

资源


我已经看过了,但是正如我告诉camh的那样,我不知道在哪个阶段执行ssh命令和其他程序命令。我已经阅读了很多手册页和其他指南
TheLQ 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.