当我尝试通过ssh
.在远程计算机上执行我的脚本之一时,我遇到了奇怪的行为。
我将脚本目录的路径添加到$PATH
我的 .profile 中。但是当我运行时ssh kalle@Raspi foo
,我得到“命令未找到”。
ssh kalle@Raspi 'echo $PATH'
给出默认值,并且使用我在 .profile 中设置和导出的变量,输出为空。
我echo foo
在.profile中放入了一个,当然,它被打印了。然后我输入set -vx
第一行,打印行的顺序很奇怪;例如,“foo”在“+echo foo”之前打印。
谁能弄清楚发生了什么事吗?
编辑:
当我这样做时ssh kalle@Raspi 'bash -lc "echo \$PATH"'
,我得到了完整的路径。
编辑2:
我很抱歉造成混乱,当我想运行远程脚本时我非常累,现在我的记忆错误了,但我现在记得我做了什么。
我尝试使用bash -lc
它后,仅使用命令不起作用,但我错过了反斜杠!所以我ssh kalle@Raspi 'bash -lc "echo $PATH"'
和往常一样,当您将命令字符串赋予另一个命令时,shell 会对该命令字符串执行各种扩展。
因此,在删除引号之后,我们将bash -lc "echo $PATH"
其作为单个参数传递ssh
并在远程计算机上执行,其中 shell 执行参数替换,即$PATH
替换为默认路径前它被传递给bash -lc
,使后者无用。
然后我很愚蠢地忘记了我正在使用bash -lc
,所以我认为ssh kalle@Raspi foo
这会导致.profile
被阅读,因为我看到了echo
我放入.profile
.
真丢脸。我一定很累了,因为当我写这个问题时,我必须用反斜杠保护变量对我来说是绝对自然的;我什至不需要考虑它。但我仍然没有意识到我现在意识到了什么。
因此,这种行为非常明显且绝对正常,但问题仍然存在。
我可以使用bash -lc
一种解决方法,根据具体情况,引用和转义可能会很麻烦,或者我可以放在. .profile
实际命令之前。
有人知道更优雅的解决方案吗?我可以在服务器上调整一些东西,以便我可以使用ssh kalle@Raspi foo
?
答案1
感谢@ilkkachu,我找到了解决方案。
我将变量内容移至.profile
一个单独的脚本中,该脚本是从.profile
.
然后,我将“如果不以交互方式运行,则不执行任何操作”部分修改.bashrc
如下:
case $- in
*i*) ;;
*)
# Not running interactively.
# Check if we are the server of an SSH connection without a PTY.
# If so, sshd is about to execute a command issued by some client,
# in which case this script has been invoked directly by sshd, not
# by .profile, so we need to set vars that are normally set in .profile
# and that are important for my scripts (like $PATH) here before returning.
# This way, I can call my scripts just via ‘ssh kalle@Raspi foo’ without
# using ‘bash -lc’.
#
# References:
# https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html
# https://man.openbsd.org/ssh#ENVIRONMENT
[[ $SSH_CONNECTION && -z $SSH_TTY ]] && . $HOME/scripts/bashrc-include/set-vars.sh
return;;
esac
编辑:
并非完全不重要:证明它有效且没有副作用。
我把 es 放在, andecho
的前面,另一个放在上面的后面。.profile
.bashrc
set-vars.sh
echo
case ... in ... esac
我应该提到的是,我在所有机器上都使用相同的.profile
东西。.bashrc
那么,让我们测试一下:
当我在写这篇文章的机器上打开终端时,我得到:
.profile: Started.
set-vars.sh: Setting vars.
.bashrc: Started.
.bashrc: Interactive shell, proceeding.
当我 ssh 进入我的 Raspi 时,我得到了完全相同的结果。
当我发出 时ssh kalle@Raspi 'echo $PATH'
,我得到:
.bashrc: Started.
set-vars.sh: Setting vars.
和正确的$PATH
.
编辑2:
用于打开和关闭消息的小脚本:
#!/bin/bash
# Author: derkallevombau
# Created 2023-04-07 12:58:48
if [[ $1 =~ ^on|1|true$ ]]; then
sedScript='"s/^#([\t ]*echo $(basename $f):.*)/\1/"'
elif [[ $1 =~ ^off|0|false$ ]]; then
sedScript='"s/^([\t ]*echo $(basename $f):.*)/#\1/"'
else
cat <<-END
Unknown argument: '$1'.
Invocation: bash-startup-messages-set (on|1|true)|(off|0|false)
END
exit
fi
for f in ~/.{profile,bashrc} /home/kalle/scripts/bashrc-include/set-vars.sh; do
eval sed -Ei $sedScript $f
done