Files
sysconfig/ssh.sh
T
2026-10-14 09:44:42 +08:00

119 lines
3.9 KiB
Bash
Executable File

#!/bin/bash
echo "Usage: $(basename $0) [host_to_ssh] [cmd_to_run]"
# Ensure jq is installed
if ! command -v jq &> /dev/null; then
echo "jq is required but not installed. Please install jq and run the script again."
exit 1
fi
# Path to the settings.json file
SETTINGS_FILE="$HOME/Library/Application Support/Code/User/settings.json"
if [[ ! -f "$SETTINGS_FILE" ]]; then
SETTINGS_FILE="../../.vscode/settings.json"
if [[ ! -f "$SETTINGS_FILE" ]]; then
echo "settings.json file not found!"
exit 1
fi
fi
# Parse the JSON to get labels and corresponding details
# 临时把 IFS 设为换行,让 =($(...)) 只按行拆分、保留 label 内部空格,
# 避免默认 IFS(空格) 拆散含空格的 label,导致每台显示两行、labels/hosts 错位
oldIFS=$IFS
IFS=$'\n'
labels=($(jq -r '.["sshfs.configs"][] | .label' "$SETTINGS_FILE"))
hosts=($(jq -r '.["sshfs.configs"][] | .host' "$SETTINGS_FILE"))
ports=($(jq -r '.["sshfs.configs"][] | .port' "$SETTINGS_FILE"))
names=($(jq -r '.["sshfs.configs"][] | .name' "$SETTINGS_FILE"))
usernames=($(jq -r '.["sshfs.configs"][] | .username' "$SETTINGS_FILE"))
passwords=($(jq -r '.["sshfs.configs"][] | .password' "$SETTINGS_FILE"))
privateKeyPaths=($(jq -r '.["sshfs.configs"][] | .privateKeyPath' "$SETTINGS_FILE"))
IFS=$oldIFS
prefixes=()
for i in "${!labels[@]}"; do
option=$(echo "${labels[$i]}" | sed 's/[^[:alnum:]].*//') # 提取前缀(前导字母数字)
prefixes+=("$option")
done
# Check if a command-line argument is provided
if [ "$1" != "" ]; then
# 如果提供了参数,则直接使用这个前缀
host_to_ssh=$1
else
echo "Select a target to connect via SSH (Enter to exit):"
echo
# 对齐前缀列:按最长前缀宽度填充
maxlen=0
for p in "${prefixes[@]}"; do
[ ${#p} -gt $maxlen ] && maxlen=${#p}
done
for i in "${!labels[@]}"; do
printf "%-*s: %s\n" "$maxlen" "${prefixes[$i]}" "${labels[$i]}"
done
echo
read -p "请输入要连接的主机前缀 (直接回车退出): " host_to_ssh
# 空输入直接退出(空前缀会误匹配到错乱的数组项,直接拦截)
if [ -z "$host_to_ssh" ]; then
echo "已退出。"
exit 0
fi
fi
echo
# 查找用户输入对应的索引
selected_index=-1
for i in "${!prefixes[@]}"; do
if [[ "${prefixes[$i]}" == "$host_to_ssh" ]]; then
selected_index=$i
break
fi
done
# 如果没有找到匹配的索引
if [ "$selected_index" -eq -1 ]; then
echo "无效的选择,请重试。"
exit 1
fi
label="${labels[$selected_index]}"
name="${names[$selected_index]}"
host="${hosts[$selected_index]}"
port="${ports[$selected_index]}"
username="${usernames[$selected_index]}"
password="${passwords[$selected_index]}"
privateKeyPath="${privateKeyPaths[$selected_index]}"
if [ "$port" = "null" ]; then
port=22
fi
if [ -n "$2" ]; then
cmd="$2"
ssh_opts="-Y -t" # 如果 $2=tmux 那么也需要 -t
else
# 未提供 $2 时,默认在远程执行:若装有 tmux 则 tmux a(附加到已有会话),否则进入交互式 shell。
# 此时必须加 -t 强制分配伪终端,否则 tmux 报 "open terminal failed: not a terminal",回退 shell 也不显示提示符
cmd='if command -v tmux >/dev/null 2>&1; then tmux new -A; else exec "${SHELL:-sh}"; fi'
ssh_opts="-Y -t"
fi
echo "::*** Connecting to ${label}"
if [ "$password" != "null" ]; then
if command -v sshpass &> /dev/null; then
echo "::*** sshpass -p $password $ssh_opts -p $port $username@$host '$cmd'"
sshpass -p "$password" ssh $ssh_opts -p "$port" "$username@$host" "$cmd"
else
echo "::*** ssh $ssh_opts -p $port $username@$host '$cmd'"
ssh $ssh_opts -p "$port" "$username@$host" "$cmd"
fi
else
echo "::*** ssh $ssh_opts -p $port $username@$host '$cmd'"
ssh $ssh_opts -p "$port" "$username@$host" "$cmd"
fi