.NETを介してリモートコンピュータでスクリプトの1つを実行しようssh
とすると、奇妙な動作が発生します。
$PATH
私の.profileにスクリプトディレクトリパスを追加しました。ただし、実行すると、ssh kalle@Raspi foo
「コマンドが見つかりません」というメッセージが表示されます。
ssh kalle@Raspi 'echo $PATH'
デフォルト値が与えられ、.profileで設定してエクスポートされた変数を使用すると、出力は空です。
.profileに1を入れたecho foo
ので、当然印刷されました。その後、最初の行を入力すると、set -vx
行は奇妙な順序で印刷されます。たとえば、「+echo foo」の前に「foo」が印刷されます。
何が起こっているのかを理解できる人はいますか?
編集する:
これにより、ssh kalle@Raspi 'bash -lc "echo \$PATH"'
フルパスが得られます。
編集2:
混乱させて申し訳ありません。リモートスクリプトを実行しようとすると非常に疲れていました。
使ってみた後、bash -lc
コマンドだけ使っても動作しませんでしたが、バックスラッシュが抜けましたね!したがって、ssh kalle@Raspi 'bash -lc "echo $PATH"'
通常のようにコマンド文字列を別のコマンドに提供すると、シェルはそのコマンド文字列に対してさまざまな拡張を実行します。
したがって、引用符を削除した後、bash -lc "echo $PATH"
それを単一のパラメータとしてssh
渡し、シェルがパラメータ置換を実行するリモートシステムで実行します。つまり、$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
編集する:
まったく重要ではないわけではありません。効果があり、副作用がないことが証明されています。
echo
andの前にはesを、topの後にはesを付けました。.profile
.bashrc
set-vars.sh
echo
case ... in ... esac
私はすべての機械で同じものを使用することに言及するべきです.profile
。.bashrc
それではテストしてみましょう。
この記事を書いているコンピュータで端末を開くと、次の結果が表示されます。
.profile: Started.
set-vars.sh: Setting vars.
.bashrc: Started.
.bashrc: Interactive shell, proceeding.
RaspiにSSHを接続すると、同じ結果が表示されます。
発行すると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