关于配置

最近经常有迁移服务器的需求,但是又嫌弃每次配置比较麻烦,就把配置存在了本地,使用脚本统一配置。

PowerShell Scripting

开始的想法是写 PowerShell Scripting,就了解了一下在编写PowerShell脚本,在PowerShell脚本中,可以使用 *param *声明参数,如下:

param($args1, $args2, $args3=default)

一旦使用这样的方式,所有的参数都必须声明在这参数组里。

但是问题是 Windows 里面没有 ssh-copy-id 这个函数,只能自己定义:

# copyid.ps1
function ssh-copy-id([string]$userAtMachine, $args){   
    $publicKey = "$ENV:USERPROFILE" + "/.ssh/id_rsa.pub"
    if (!(Test-Path "$publicKey")){
        Write-Error "ERROR: failed to open ID file '$publicKey': No such file"            
    }
    else {
        # Write-Output $userAtMachine
        & cat "$publicKey" | ssh $args $userAtMachine -tt "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys || exit 1"      
    }
}

ssh-copy-id $args[0]

Python 脚本

服务器文件传输

首先是处理 config 文件以及通过 os.system 将需要的内容传到服务器上

# settmux.py: python settmux.py abbr addr [port]
import sys
import os
from subprocess import call
import paramiko, time
import platform

os.system('cp /mnt/c/Users/China/.ssh/config /root/.ssh/')
print("[INFO]: Moving config in to /root/.ssh/")

# Args processing
username = "name"
args = sys.argv
print(f"[INFO]: Getting {len(args)} args: {args}")
if len(args) == 3:
    port = "22"
    _, abbr, addr = args
else:
    _, abbr, addr, port = args

# Get config file and processing
with open("/root/.ssh/config", 'r') as f:
    OCCUPIED = False
    context = f.read()
    context = context.split("\n")
with open("/root/.ssh/config", 'a') as f:
    for line in context:
        line = line.split("#")[0].strip()
        if line == "":
            continue
        kind = line.split(" ")[0]
        if kind == 'HostName':
            config_addr = line.split(" ")[1]
            if addr == config_addr:
                print("[INFO]: Already have config")
                OCCUPIED = True
    if not OCCUPIED:
        f.write(f"\n\nHost {abbr}\n  HostName {addr}\n  Port {port}\n  User {username}")

# Using platform to check the platform
if platform.system().lower() == 'windows':
    os.system(f".\ssh-copy-id {abbr}")
elif platform.system().lower() == 'linux':
    os.system(f"ssh-copy-id -i /mnt/c/Users/China/.ssh/id_rsa.pub {abbr}")
# SCP all the needed files
os.system(f"scp -r ./serverconfig/.tmux/ {username}@{abbr}:~/.tmux")
os.system(f"scp ./serverconfig/.bashrc {username}@{abbr}:~/")
os.system(f"scp ./serverconfig/.tmux.conf {username}@{abbr}:~/")

首先处理参数,然后根据 config 文件获得内容,注意,(就目前我的知识水平而言)在打开文件的时候无法同时进入可读之前内容与可添加的模式,虽然存在”a+”的扩展模式,但由于”a”模式下光标将位于文件末尾,因此需要打开两次。

通过在不同平台下的判断将 id_rsa.pub 上传到服务器之后就可以通过 Host 免密登陆了。

服务器文件执行

然后是在本地执行服务器端的配置文件生效的操作。这里我了解到paramiko库,所以使用了一下

import sys
import os
from subprocess import call
import paramiko, time
from collections import defaultdict

# Reading configs
with open("/root/.ssh/config", 'r') as f:
    OCCUPIED = False
    context = f.read()
    context = context.split("\n")
config = defaultdict(dict)
for line in context:
    line = line.split("#")[0].strip()
    if line == "":
        continue
    kind = line.split(" ")[0]
    if kind == 'Host':
        temp_name = line.split(" ")[1]
    elif kind == 'Port':
        config[temp_name]['port'] = line.split(" ")[1]
    elif 'jump' in temp_name:
        continue
    elif kind == 'HostName':
        config[temp_name]['hostname'] = line.split(" ")[1]
    elif kind == 'User':
        config[temp_name]['user'] = line.split(" ")[1]
    else:
        print("[INFO]: Not known args")
print(f"[INFO]: CONFIG is")
for conf in config:
    print(conf, config[conf])
username = "name"
abbr = sys.argv[1]
addr = config[abbr]['hostname']
port = config[abbr]['port'] if 'port' in config[abbr] else '22'

# Using the private key to log in without a password
pkey='/root/.ssh/id_rsa'
key=paramiko.RSAKey.from_private_key_file(pkey)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(addr, port, username, pkey=key)

# Setting tmux config
stdin, stdout, stderr = ssh.exec_command('tmux new -s Tiberius')
stdin, stdout, stderr = ssh.exec_command('tmux source-file ~/.tmux.conf')
out = stdout.read().decode('utf8')
err = stderr.read().decode('utf8')
result = [out, err]
print(f"[INFO]: result of command {result}") 

# Downloading Anaconda
stdin, stdout, stderr = ssh.exec_command('wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-5.3.1-Linux-x86_64.sh')
out = stdout.read().decode('utf8')
err = stderr.read().decode('utf8')
result = [out, err]
print(f"[INFO]: result of command {result}") 

ssh.close()

通过私钥配置免密登录,配置后设置tmux的操作以及下载anaconda,随后只需要scp将环境传输到新的anaconda上即可。

显示Git分支

如何在Linux下显示当前git分支 - 知乎 (zhihu.com)