![当我 sshpass 到服务器时找不到brew](https://linux22.com/image/161050/%E5%BD%93%E6%88%91%20sshpass%20%E5%88%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%97%B6%E6%89%BE%E4%B8%8D%E5%88%B0brew.png)
brew 安装在服务器上,但是当我 sshpass 到服务器时,它会抛出异常,bash: brew: command not found
ideviceinstaller 也会发生同样的情况bash: ideviceinstaller: command not found
这是我正在使用的命令
sshpass -p password ssh -oStrictHostKeyChecking=no -oCheckHostIP=no user@**** 'cd /Users/user/Documents/workspace/iOS; brew'
sshpass -p password ssh -oStrictHostKeyChecking=no -oCheckHostIP=no user@**** 'cd /Users/user/Documents/workspace/iOS; ideviceinstaller -l'
我有完全相同的 .bashrc 和 .bash_profile。
[[ -s "$HOME/.profile" ]] && source "$HOME/.profile" # Load the default .profile
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*
export ANDROID_HOME=/Users/user/Library/Android/sdk
export GIT_SSH_COMMAND='ssh -o KexAlgorithms=+diffie-hellman-group1-sha1'
export PATH=$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH
# Setting PATH for Python 3.7
# The original version is saved in .bash_profile.pysave
PATH="/Library/Frameworks/Python.framework/Versions/3.7/bin:${PATH}"
export PATH
。轮廓
# Add RVM to PATH for scripting. Make sure this is the last PATH variable change.
export PATH="$PATH:$HOME/.rvm/bin"
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*
不知道我犯了什么错误。请帮忙
答案1
shell 选择它执行的登录脚本的方式组合ssh
和众所周知的不直观方式让您感到困惑。bash
从ssh(1)
手册页(强调我的):
当服务器接受用户的身份时,服务器要么在非交互式会话中执行给定的命令或者,如果未指定命令,则登录计算机并为用户提供普通 shell 作为交互式会话。 [...]
如果请求交互式会话,则默认情况下,当客户端有伪终端 (pty) 时,ssh 只会请求交互式会话的伪终端 (pty)。 [...]
如果没有分配伪终端,则会话是透明的并且可以用于可靠地传输二进制数据。
它没有明确说明,但是当您指定要在远程端运行的命令时,ssh
假定您正在运行非交互式会话,并且不会在远程端分配伪终端(pty),除非您使用-t
选项到ssh
.
事实证明,这对于远程端的 shell 很重要。
从bash(1)
手册页:
A登录外壳参数零的第一个字符是 - ,或者以选项开头
--login
。一个交互式外壳是一种不带非选项参数(除非
-s
指定)且不带-c
其标准输入和错误都连接到终端(由 确定isatty(3)
)的选项的选项,或者是使用该-i
选项开始的选项。 [...]
你没有(伪)终端,并且有一个命令作为一组非选项参数运行,所以bash
开始作为非交互式登录 shell。那么在这种情况下它会运行什么脚本呢?
当 bash 作为交互式登录 shell 被调用时,或者作为带有 --login 选项的非交互式 shell,它首先从文件中读取并执行命令
/etc/profile
(如果该文件存在)。读取该文件后,它会按顺序查找~/.bash_profile
、~/.bash_login
、 和~/.profile
,并从第一个存在且可读的文件中读取并执行命令。
因此,/etc/profile
和 your~/.bash_profile
可能会也可能不会被执行,具体取决于您的 shell 是否获得显式--login
选项。
怎么样~/.bashrc
?
当交互式外壳启动非登录 shell 时,bash 会从 /etc/bash.bashrc 和 ~/.bashrc 读取并执行命令(如果这些文件存在)。
so~/.bashrc
仅适用于交互式 shell,将被跳过,就像 一样/etc/bash.bashrc
。
当 bash 以非交互方式启动时,要运行 shell 脚本,例如,它会在环境中查找变量 BASH_ENV,如果出现该变量,则扩展其值,并使用扩展后的值作为要读取和执行的文件名。 Bash 的行为就像执行了以下命令:
`if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi`
但 PATH 变量的值不用于搜索文件名。
因此,除非$BASH_ENV
设置(通过sshd
或系统默认环境),这将是不寻常的,那么有可能根本不会执行任何登录脚本在非交互式登录的情况下。
因此,当您运行非交互式命令时,您的 PATH 可能比平常短得多。您可以通过以下方式自行验证:
local$ ssh remote
remote$ printenv PATH
/usr/local/sbin:/Users/<username>/perl5/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
remote$ exit
local$ ssh remote printenv PATH
/usr/bin:/bin:/usr/sbin:/sbin
此示例是使用 macOS 10.14.6 作为远程主机创建的。请注意,特别/usr/local/bin
是在非交互式会话的 PATH 中缺少该内容。
作为一种解决方法,您可能必须显式获取一个或多个正常登录脚本。例子:
local$ ssh remote "source /etc/profile; printenv PATH"
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/MacGPG2/bin:/opt/X11/bin
请注意,路径更好,但仍然与交互式登录中的不太一样,并且采购~/.bashrc
没有帮助。事实证明,这是因为我~/.bashrc
一开始就有这个:
if [ -z "$PS1" ]; then
return
fi
在非交互式 shell 上,不会设置“$PS1”。因此,此测试会导致~/.bashrc
在非交互式会话中跳过整个测试。
登录脚本中生成输出的任何内容应该被此类测试封装,或者通过 SSH 会话传输内容的事物(例如 )scp
,rsync
或者git pull
可能会因遇到意外的脚本输出而不是它们正在等待的应用程序协议数据而失败。