三 linux 远程服务器的常用操作封装

三 linux 远程服务器的常用操作封装

【动机】

与 linux 远程服务器,例如常见的 ECS 通信,不外乎连接,登录(可选是否使用 key),修改 ssh 端口号,上传,下载,运行程序等操作,这些操作如果不用图形界面的程序进行,而是仅仅在客户端控制台上运行命令是可行的,但是需要记住所有的命令细节(或者随时准备翻看自己的“命令笔记”),如何在不使用图形界面的情况下,简化这些操作?

阅读更多:三 linux 远程服务器的常用操作封装

【意图】

将所有的需要的命令细节封装起来,以菜单项的形式展示然后运行。例如配置使用密钥登录:

  1. 核实服务器是否存在公钥文件,如存在责删除脏记录(如果有);
  2. 检查客户端是否存在密钥文件,不存在则使用 ssh-keygen 生成密钥对;
  3. 使用 sshpass 结合 ssh-copy-id 复制公钥到远程服务器,即将新的公钥记录重写入服务器公钥文件;
  4. 确保客户端 ssh 配置文件正确。

将其封装到一个函数 key_enable 中即可。

【实现】

此处仅展示入口脚本 main.sh,完整的打包后的脚本,参见源码下载

#!/bin/bash


# rely:
# 1. sshpass: 将密码命令

set -e 

# global constant:
declare -r __DEBUG__=
declare -r ROOT_DIR_PATH=$(dirname $(readlink -f $0))
declare -r ROOT_DIR_NAME=$(basename $ROOT_DIR_PATH)
declare -r ENTRY_FILE_NAME=${BASH_SOURCE[0]##*/}
declare -r ENTRY_FILE_PATH=$ROOT_DIR_PATH/$ENTRY_FILE_NAME
declare -r TARGET_EXE_NAME=${ENTRY_FILE_NAME%.*}
declare -r CONFIG_FILE_REL_PATH="data/config.json"
declare -r CONFIG_FILE_PATH="$ROOT_DIR_PATH/$CONFIG_FILE_REL_PATH"
declare -r DEFAULT_CONFIG_ROOT="default"

# 根据当前脚本与 library 和 execution 的相对位置, .. 可能有所变化
declare -r LNX_LIB_DIR="$ROOT_DIR_PATH/../../library"
declare -r TARGET_EXE_PATH="$ROOT_DIR_PATH/../../execution/$ROOT_DIR_NAME/$TARGET_EXE_NAME"

# region Sourcing
# 块 source, 详情查看 library/doc/compile.txt
for file in \
    $(find $ROOT_DIR_PATH \
        -type f -regex .*?\.sh$ \
        -not -wholename "$ENTRY_FILE_PATH" ) \
    $(find $LNX_LIB_DIR \
        -type f -regex .*?\.sh$ ) ; do
      source $file
done
# endregion Sourcing 

declare __JSON_CONTENT__=$(jq . $CONFIG_FILE_PATH)
[ -z "$__JSON_CONTENT__" ] && error "$json.config 尚未准备好!" && exit 0 

  __TEST__=

  # 如果采用 [ ... ] && ... || ... 的形式, 当 choose_ecs 退出码非 0 时,
  # 将继续执行 unit_test_start, 这可能不是需要的 
  if [  -z "$__TEST__" ]; then
      clear
      choose_ecs
  else
      unit_test_start
  fi
  # [  -z "$__TEST__" ] && choose_ecs || unit_test_start 
aop success left "Thanks for your use. Byebye!"

# region Ignored
# 自编译部分, 详情查看 library/doc/compile.txt
# 一般只有 -a 部分需要修改, 即使保存原样, 最多是 error.log 中增加了记录
if [ "$1" ]; then
    keep_config_secret
    menu "start compiling ..."
    cmdline="script2execution 
            --target-path \"$TARGET_EXE_PATH\"  
            --attaches \"$CONFIG_FILE_REL_PATH\"
            --cmdline-when-over keep_config_secret
            --give-up-self-compile
        "
    perform --prompt "编译中, 请稍候......" --cmdline "$cmdline" -d 0.2
    aop "success -e" center "Compiling finished."
    # 恢复本地 json 文件
    echo $__JSON_CONTENT__ | jq . > $CONFIG_FILE_PATH --tab
fi
#endregion Ignored

文件 config.json,用于保存远程服务器属性,以及脚本用到的变量:

{
  "default": {
    "sshd": {
      "key": {
        "filepath": "~/.ssh/authorized_keys"
      },
      "config": {
        "filepath": "/etc/ssh/sshd_config",
        "allowpath": "/etc/hosts.allow",
        "denypath": "/etc/hosts.deny",
        "login": {
          "welcome": {
            "dirname": "update-motd.d",
            "sysparent": "/etc",
            "bakparent": "/app/freezone/etc"
          }
        }
      }
    },
    "ssh": {
      "keygen": {
        "defaultpath": "~/.ssh",
        "dirpath": "/app/freezone/.ssh",
        "filenamefmt": "%s_rsa",
        "commentfmt": "login to %s ecs",
        "configfilename": "hosts"
      }
    },
    "code": {
      "reboottimeout": 26,
      "cmdtimeout": 10,
      "prompt": {
        "configerror": "server and (or) client config error, please check these files:",
        "tasksuccess": "congratulations! All the work has been done successfully."
      },
      "deploy": {
        "server": {
          "app": "/app/freezone/execution",
          "lib": "obsoleted"
        },
        "client": {
          "apps": "/mnt/d/Estate/asset/OS/linux/execution/wordpress_in_docker",
          "libs": "obsoleted"
        }
      },
      "relies": "bc jq bypy docker rsync"
    }
  },
  "huawei": {
    "sshd": {
      "config": {
        "login": {
          // "user": "远程登录服务器使用的用户名待填入",
          // "password": "远程登录服务器使用的用户名对应的密码待填入",
          "port": {
            "default": 22,
            // "custom": "自定义的 ssh 登录使用的端口待填入"
          },
          // "addr": "远程服务器的外网 ip 或者域名待填入"
        },
        // "title": "远程服务器名称,用于标识服务器待填入"
      }
    }
  },
  "ali": {
    "sshd": {
      "config": {
        "login": {
          // "user": "远程登录服务器使用的用户名待填入",
          // "password": "远程登录服务器使用的用户名对应的密码待填入",
          "port": {
            "default": 22,
            // "custom": "自定义的 ssh 登录使用的端口待填入"
          },
          // "addr": "远程服务器的外网 ip 或者域名待填入"
        },
        // "title": "远程服务器名称,用于标识服务器待填入"
      }
    }
  },
  "tencent": {
    "sshd": {
      "config": {
        "login": {
          // "user": "远程登录服务器使用的用户名待填入",
          // "password": "远程登录服务器使用的用户名对应的密码待填入",
          "port": {
            "default": 22,
            // "custom": "自定义的 ssh 登录使用的端口待填入"
          },
          // "addr": "远程服务器的外网 ip 或者域名待填入"
        },
        // "title": "远程服务器名称,用于标识服务器待填入"
      }
    }
  }
}

被 // 注释的行,需要根据实际情况修改。

【效果】

完成的基本操作是:

  1. ssh 端口切换(在自定义端口和标准22号端口之间)
  2. 启用(停用) ssk key 登录
  3. 启用(停用)服务器的远程登录欢迎信息
  4. 上传(下载)脚本或者其他任何文件
  5. 打开远程终端,在此可以执行以上未包含的操作。

谢谢收看!