通过 ssh 的 sh 启动文件

通过 ssh 的 sh 启动文件

在任何 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

~/.profile仅由登录 shell 执行。调用 shell 的程序决定该 shell 是否为登录 shell(通过将 a-作为 shell 调用中第 0 个参数的第一个字符)。当您登录执行特定命令时,它通常不会被执行。

特别是,仅当您未指定命令时,OpenSSH 才会调用登录 shell。因此,如果您确实指定了命令,~/.profile则不会被读取。

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

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

我认为只要您使用公钥身份验证,总是有效的一件事(很奇怪)就是(ab)使用文件command=中的选项authorized_keys。带选项的键command仅适用于运行指定的命令;但文件中的命令authorized_keys运行时环境变量SSH_ORIGINAL_COMMAND设置为用户指定的命令。如果用户未指定命令并因此需要交互式 shell,则此变量为空。所以你可以使用这样的东西~/.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##*/}" "$@"

然后建立指向该脚本的符号链接rsync,称为 、 等。在命令行上unison传递,依此类推以用于其他程序。或者,某些命令允许您指定要远程运行的整个 shell 片段,这允许您使命令独立:例如,对于 rsync,您可以使用.--rsync-path='bin/rsync'rsync--rsync-path='. ~/.profile; rsync'

还有另一种途径,具体取决于您的登录 shell 是 bash 还是 zsh。 Bash~/.bashrc在被 rshd 或 sshd 调用时总是读取,即使它不是交互式的(但如果它被称为 as 则不会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

答案2

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

ssh name@host echo $PATH

几乎永远不会有用。 $PATH 的变量替换由本地 shell 完成,并传递给 ssh,后者在远程系统上执行 echo 以打印路径变量的内容,因为它在本地系统上扩展。下面是我在我的 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 扩展变量。

答案3

通常在登录时,bash 会从以下位置读取命令:

〜/ .bash_profile
〜/ .bashrc

来自 bash 手册页:

~/.bash_profile
个人初始化文件,为登录 shell 执行

~/.bashrc
每个交互式 shell 的单独启动文件

答案4

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

更新

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

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

如果它不是登录 shell,则会评估环境变量 ENV,并将生成的文件名作为启动文件的名称。

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

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

  • argv[0] 中的基本文件名是 sh (:!: 亲爱的超级聪明的 Linux 用户请注意... /bin/sh 可能链接到 /bin/bash,但这并不意味着它的行为类似于 /bin/bash :!:)

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

来源

相关内容