fix: 把 SSH config.d Include 写到 ~/.ssh/config 第一行
Include 落在 Host/Match 之后会被当成该块的条件引入。ssh2 与 ff ssh 改为检测顶层 Include,缺失时插入文件首行并去掉块内重复项。
This commit is contained in:
+100
-16
@@ -29,6 +29,43 @@ function __ff_ssh_ensure_keys
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function __ff_ssh_has_toplevel_include --argument ssh_config
|
||||||
|
awk '
|
||||||
|
tolower($1) == "host" || tolower($1) == "match" { saw_block = 1 }
|
||||||
|
tolower($1) == "include" {
|
||||||
|
for (i = 2; i <= NF; i++) {
|
||||||
|
if (tolower($i) ~ /(^|\/)config\.d\/\*/) {
|
||||||
|
if (!saw_block) found_ok = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END { exit(found_ok ? 0 : 1) }
|
||||||
|
' "$ssh_config"
|
||||||
|
end
|
||||||
|
|
||||||
|
function __ff_ssh_prepend_include --argument ssh_config include_line
|
||||||
|
set -l tmp (mktemp)
|
||||||
|
awk -v include_line="$include_line" '
|
||||||
|
function is_config_d_include() {
|
||||||
|
if (tolower($1) != "include") {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for (i = 2; i <= NF; i++) {
|
||||||
|
if (tolower($i) ~ /(^|\/)config\.d\/\*/) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
BEGIN { print include_line }
|
||||||
|
is_config_d_include() { next }
|
||||||
|
{ print }
|
||||||
|
' "$ssh_config" > $tmp
|
||||||
|
cp $tmp "$ssh_config"
|
||||||
|
rm -f $tmp
|
||||||
|
chmod 600 "$ssh_config"
|
||||||
|
end
|
||||||
|
|
||||||
function __ff_ssh_ensure_config_d
|
function __ff_ssh_ensure_config_d
|
||||||
set -l ssh_config "$HOME/.ssh/config"
|
set -l ssh_config "$HOME/.ssh/config"
|
||||||
set -l include_line "Include ~/.ssh/config.d/*"
|
set -l include_line "Include ~/.ssh/config.d/*"
|
||||||
@@ -36,15 +73,22 @@ function __ff_ssh_ensure_config_d
|
|||||||
chmod 700 "$HOME/.ssh"
|
chmod 700 "$HOME/.ssh"
|
||||||
|
|
||||||
if not test -f $ssh_config
|
if not test -f $ssh_config
|
||||||
printf '%s\n' $include_line > $ssh_config
|
printf '%s\n' "$include_line" > $ssh_config
|
||||||
chmod 600 $ssh_config
|
chmod 600 $ssh_config
|
||||||
echo "Created $ssh_config with $include_line"
|
echo "Created $ssh_config with $include_line"
|
||||||
else if grep -qE 'Include[[:space:]]+.*config\.d' $ssh_config
|
return
|
||||||
echo "config.d Include already in $ssh_config"
|
|
||||||
else
|
|
||||||
printf '\n# config.d\n%s\n' $include_line >> $ssh_config
|
|
||||||
echo "Appended to $ssh_config: $include_line"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
chmod 600 $ssh_config
|
||||||
|
if __ff_ssh_has_toplevel_include $ssh_config
|
||||||
|
echo "config.d Include already in $ssh_config"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l backup "$ssh_config.backup."(date +%Y%m%d%H%M%S)
|
||||||
|
cp -p $ssh_config $backup
|
||||||
|
__ff_ssh_prepend_include $ssh_config "$include_line"
|
||||||
|
echo "Prepended to $ssh_config: $include_line (backup $backup)"
|
||||||
end
|
end
|
||||||
|
|
||||||
function __ff_ssh_resolve_path --argument path
|
function __ff_ssh_resolve_path --argument path
|
||||||
@@ -58,22 +102,62 @@ function __ff_ssh_resolve_path --argument path
|
|||||||
end
|
end
|
||||||
|
|
||||||
function __ff_ssh_remote_has_include --argument host
|
function __ff_ssh_remote_has_include --argument host
|
||||||
ssh -q $host 'test -f ~/.ssh/config && grep -qE "Include[[:space:]]+.*config\.d" ~/.ssh/config'
|
set -l script 'test -f ~/.ssh/config && awk "
|
||||||
|
tolower(\$1) == \"host\" || tolower(\$1) == \"match\" { saw_block = 1 }
|
||||||
|
tolower(\$1) == \"include\" {
|
||||||
|
for (i = 2; i <= NF; i++) {
|
||||||
|
if (tolower(\$i) ~ /(^|\/)config\.d\/\*/) {
|
||||||
|
if (!saw_block) found_ok = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END { exit(found_ok ? 0 : 1) }
|
||||||
|
" ~/.ssh/config'
|
||||||
|
printf '%s\n' "$script" | ssh -qT $host sh -s
|
||||||
end
|
end
|
||||||
|
|
||||||
function __ff_ssh_remote_ensure_include --argument host
|
function __ff_ssh_remote_ensure_include --argument host
|
||||||
ssh $host 'mkdir -p ~/.ssh/config.d && chmod 700 ~/.ssh
|
set -l script 'mkdir -p ~/.ssh/config.d && chmod 700 ~/.ssh
|
||||||
if [ -f ~/.ssh/config ] && grep -qE "Include[[:space:]]+.*config\.d" ~/.ssh/config; then
|
include_line="Include ~/.ssh/config.d/*"
|
||||||
echo "Remote config.d Include already exists"
|
has_toplevel() {
|
||||||
elif [ -f ~/.ssh/config ]; then
|
awk "
|
||||||
printf "\n# config.d\nInclude ~/.ssh/config.d/*\n" >> ~/.ssh/config
|
tolower(\$1) == \"host\" || tolower(\$1) == \"match\" { saw_block = 1 }
|
||||||
chmod 600 ~/.ssh/config
|
tolower(\$1) == \"include\" {
|
||||||
echo "Appended config.d Include on remote"
|
for (i = 2; i <= NF; i++) {
|
||||||
else
|
if (tolower(\$i) ~ /(^|\/)config\.d\/\*/) {
|
||||||
printf "%s\n" "Include ~/.ssh/config.d/*" > ~/.ssh/config
|
if (!saw_block) found_ok = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END { exit(found_ok ? 0 : 1) }
|
||||||
|
" ~/.ssh/config
|
||||||
|
}
|
||||||
|
if [ ! -f ~/.ssh/config ]; then
|
||||||
|
printf "%s\n" "$include_line" > ~/.ssh/config
|
||||||
chmod 600 ~/.ssh/config
|
chmod 600 ~/.ssh/config
|
||||||
echo "Created remote config with config.d Include"
|
echo "Created remote config with config.d Include"
|
||||||
|
elif has_toplevel; then
|
||||||
|
echo "Remote config.d Include already exists"
|
||||||
|
else
|
||||||
|
tmp=$(mktemp)
|
||||||
|
awk -v include_line="$include_line" "
|
||||||
|
function is_config_d_include() {
|
||||||
|
if (tolower(\$1) != \"include\") return 0
|
||||||
|
for (i = 2; i <= NF; i++) {
|
||||||
|
if (tolower(\$i) ~ /(^|\/)config\.d\/\*/) return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
BEGIN { print include_line }
|
||||||
|
is_config_d_include() { next }
|
||||||
|
{ print }
|
||||||
|
" ~/.ssh/config > "$tmp"
|
||||||
|
cp "$tmp" ~/.ssh/config
|
||||||
|
rm -f "$tmp"
|
||||||
|
chmod 600 ~/.ssh/config
|
||||||
|
echo "Prepended config.d Include on remote"
|
||||||
fi'
|
fi'
|
||||||
|
printf '%s\n' "$script" | ssh -T $host sh -s
|
||||||
end
|
end
|
||||||
|
|
||||||
function __ff_ssh_resolve_copy_src --argument file
|
function __ff_ssh_resolve_copy_src --argument file
|
||||||
|
|||||||
+29
-15
@@ -166,6 +166,21 @@ find_alias_file() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Include 出现在 Host/Match 之后会被当成该块的条件引入,必须写在文件最前面。
|
||||||
|
ssh_config_has_toplevel_include() {
|
||||||
|
awk '
|
||||||
|
tolower($1) == "host" || tolower($1) == "match" { saw_block = 1 }
|
||||||
|
tolower($1) == "include" {
|
||||||
|
for (i = 2; i <= NF; i++) {
|
||||||
|
if (tolower($i) ~ /(^|\/)config\.d\/\*/) {
|
||||||
|
if (!saw_block) found_ok = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END { exit(found_ok ? 0 : 1) }
|
||||||
|
' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
ensure_config_include() {
|
ensure_config_include() {
|
||||||
mkdir -p "$SSH_CONFIG_DIR"
|
mkdir -p "$SSH_CONFIG_DIR"
|
||||||
chmod 700 "$SSH_DIR" "$SSH_CONFIG_DIR"
|
chmod 700 "$SSH_DIR" "$SSH_CONFIG_DIR"
|
||||||
@@ -177,17 +192,8 @@ ensure_config_include() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if awk '
|
|
||||||
tolower($1) == "include" {
|
|
||||||
for (i = 2; i <= NF; i++) {
|
|
||||||
if (tolower($i) ~ /(^|\/)config\.d\/\*/) {
|
|
||||||
found = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
END { exit(found ? 0 : 1) }
|
|
||||||
' "$SSH_CONFIG"; then
|
|
||||||
chmod 600 "$SSH_CONFIG"
|
chmod 600 "$SSH_CONFIG"
|
||||||
|
if ssh_config_has_toplevel_include "$SSH_CONFIG"; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -198,18 +204,26 @@ ensure_config_include() {
|
|||||||
cp -p "$SSH_CONFIG" "$backup"
|
cp -p "$SSH_CONFIG" "$backup"
|
||||||
|
|
||||||
awk -v include_line="$INCLUDE_LINE" '
|
awk -v include_line="$INCLUDE_LINE" '
|
||||||
BEGIN {
|
function is_config_d_include() {
|
||||||
print "# Managed SSH config fragments"
|
if (tolower($1) != "include") {
|
||||||
print include_line
|
return 0
|
||||||
print ""
|
|
||||||
}
|
}
|
||||||
|
for (i = 2; i <= NF; i++) {
|
||||||
|
if (tolower($i) ~ /(^|\/)config\.d\/\*/) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
BEGIN { print include_line }
|
||||||
|
is_config_d_include() { next }
|
||||||
{ print }
|
{ print }
|
||||||
' "$SSH_CONFIG" >"$tmp"
|
' "$SSH_CONFIG" >"$tmp"
|
||||||
|
|
||||||
cp "$tmp" "$SSH_CONFIG"
|
cp "$tmp" "$SSH_CONFIG"
|
||||||
rm -f "$tmp"
|
rm -f "$tmp"
|
||||||
chmod 600 "$SSH_CONFIG"
|
chmod 600 "$SSH_CONFIG"
|
||||||
echo "已在 $SSH_CONFIG 中加入 config.d,并备份到 $backup"
|
echo "已在 $SSH_CONFIG 第一行加入 config.d Include,并备份到 $backup"
|
||||||
}
|
}
|
||||||
|
|
||||||
alias_name=""
|
alias_name=""
|
||||||
|
|||||||
Reference in New Issue
Block a user