有时候我们的ansible-playbook我们希望定时执行以确保线上环境的状态,例如,每天定时执行一次,保证nginx的配置文件是最新的
这个时候,我们就要面临一个问题,如何让ansible-playbook使用指定 的key来执行,例如
1 |
*/1 * * * * /home/ansible/ansible-playbook test.yml |
ansible是无法自动加载.ssh/id_rsa来连接目标主机的(crontab状态下),
虽然,我们在命令行下可以不额外添加key,可以直接运行/home/ansible/ansible-playbook test.yml 命令行下是可以自动加载.ssh/id_rsa
这个时候我们需要在执行playbook前加载我们指定的ssh-key,这个时候我们就需要ssh-agent来帮我们实现
基本原理:
情况1:已经存在ssh-agent 那么尝试添加指定key到ssh-agent ,然后执行playbook
情况2:不存在ssh-agent,那么打开一个ssh-agent,然后执行playbook
程序是如何判断是否存在ssh-agent进程的呢?通过环境变量中是否存在SSH_AGENT_PID,存在说明已经有了,不存在说明没有
如果我们执行ansible-playbook 的 crontab 所在的用户在我们设置完crontab后就退出的情况下,环境变量是不可能存在的,所以这种情况下,每次都会临时打开一个ssh-agent ,corntab运行结束后ssh-agent就会被销毁(哪怕存在ssh-agent的进程,环境变量的问题,导致脚本会认为不存在)
具体脚本
1 2 |
crontab -l; */1 * * * * /home/ansible/autokeys_loader.sh /home/ansible/ansible-playbook test.yml |
来看一下autokeys_loader.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
$cat autokeys_loader.sh #!/bin/bash if [ "$#" == '0' -o "$1" == '-h' -o "$1" == '-c' -a "$#" == '1' ]; then echo 'Autokeys loader - adds autokeys to a temporary ssh-agent, then runs commands' echo "Usage: $0 <command> [args...]" echo " or $0 -c <shell command>" echo "Example: $0 ssh user@host.example.com ls" echo "Example: $0 -c 'for i in {001..999}; do ssh host$i.example.com ls; done'" exit fi trap_cmd='' # assume that a reachable, running agent means these keys aren't needed if [ -z "$SSH_AUTH_SOCK" -o ! -r "$SSH_AUTH_SOCK" ]; then echo "need add key" eval $(ssh-agent -s) > /dev/null # kill the newly-created ssh-agent when this script exits trap_cmd="kill '$SSH_AGENT_PID'" trap "$trap_cmd" EXIT OUTPUT=$(setsid ssh-add /home/ansible/id_rsa_test 2>&1) echo "done the add" if [ "$?" -ne 0 ]; then echo "$OUTPUT" echo "Failed to add ssh key '" exit 1 fi else OUTPUT=$(setsid ssh-add /home/ansible/id_rsa_test 2>&1) echo "ssh agent already exist , only try to add key " if [ "$?" -ne 0 ]; then echo "$OUTPUT" echo "Failed to add ssh key '" exit 1 fi #statements fi if [ "$1" == "-c" ]; then # since bash doesn't have a very nice way of running a shell commmand that is # in a string in an existing shell, we'll exec a new one and pass our trap # command to it so that it will clean up after running the user's command # note: "bash -c <command>" takes optional parameters after the command. # Nobody uses this feature, but just in case, we'll forward additional # paramaters with the "${@:3}" exec bash -c "trap \"$trap_cmd\" EXIT; $2" "${@:3}" else # $1 becomes the command, with any $2..$# passed as individual arguments to it "$@" # pass the return code from the command back to the user exit $? fi # should never make it here. exec failed? exit 1 |
这样操作后,crontab就可以完美执行了
附上ansible playbook
1 2 3 4 5 6 7 8 9 10 11 |
--- - hosts: 503error remote_user: ttttt tasks: - name: write a file with date copy: content: "{{ ansible_date_time }}" dest: "/home/autoOps/{{ ansible_date_time.iso8601_basic_short }}.txt" |
Latest posts by Zhiming Zhang (see all)
- aws eks node 自动化扩展工具 Karpenter - 8月 10, 2022
- ReplicationController and ReplicaSet in Kubernetes - 12月 20, 2021
- public key fingerprint - 5月 27, 2021