1. Ansible安装
yum install ansible -y
2. Ansible基础元素介绍
1. Ansible目录结构介绍
2. Ansible配置文件解析
Ansible读取配置文件的顺序依次是当前命令执行目录----用户家目录下的.ansible.cfg----/etc/ansible.cfg
3. Ansible系统命令
1. ansible 临时需要的操作
2. ansible-galaxy
查找和安装优秀的Roles,下载地址:https://galaxy.ansible.com
ansible-galaxy [init|info|install|list|remove] [--help] [options]
3. ansible-pull
有数量巨大的机器需要配置
当目标主机没有网络的时候
4. ansible-doc
模块说明文档
5. ansible-playbook
6. ansible-vault 给指定的文件进行信息加密,防止敏感信息
ansible-vault encrypt a.yml
ansible-vault decrypt a.yml
7. ansible-console
交互式工具
4. Ansible Inventory配置及详解
1. 获取指定主机或组的信息
ansible -i /etc/ansible/hosts web-elk -m ping
ansible all -m ping --limit web-elk
2. 定义主机和组
[web-elk]
192.168.1.38
192.168.1.38:222
web1.zhen.com
web[1:5].zhen.com web1.zhen.com web2.zhen.com ...web5.zhen.com
3. 定义主机变量
[web-elk]
192.168.1.38 http_port=808
4. 定义组变量
[web-elk]
192.168.1.38
[web-elk:vars]
http_port=8080
5. 定义组嵌套及组变量
[apache]
httpd.zhen.com
[nginx]
ngx1.zhen.com
[webservers:children]
apache
nginx
组嵌套只能用在playbook中,ansible不支持
6. 多重变量定义
变量通常从4个位置检索
Inventory配置文件(/etc/ansible/hosts)
playbook中vars定义的区域
Roles中vars目录下的文件
Roles同级目录group_vars和hosts_vars目录下的文件
5. ansible与正则
1. All 全量匹配
ansible all -m ping
ansible "*" -m ping
2. 逻辑或匹配
ansible "web1:web2" -m ping
3. 逻辑非匹配
ansible webservers:!phoenix 在webservers组中,但是不在phoenix组中的主机
4. 逻辑与匹配
ansible webservers:&phoenix 在webservers组中,同时又在phoenix组中的主机
5. 索引匹配
ansible webservers[0] -m ping 第一个组成员
6. 正则匹配
ansible "~(beta|web|green)\.zhen\.com" -m ping
3. Ansible Ad-Hoc命令集
1. 用法
ansible <host-pattern> [options]
2. 常用选项
-v 输出详细的执行过程信息
-vvv 可得到执行过程所有信息
-i PATH 指定inventory,默认为/etc/ansible/hosts
-f NUM 并发线程数,默认5个线程
-m NAME 指定执行使用的模块
-a 'ARGUMENTS' 模块参数
-s 相当于linux的sudo命令
-u USERNAME 指定远程主机以USERNAME运行命令
-k 认证密码
-K sudo用户的密码
3. 常用模块
1. 显示所有模块
ansible-doc -l
2. 显示某个模块
ansible-doc -s yum
3. command模块
ansible test -m command -a 'date'
ansible test -a 'date'
4. cron模块
创建定时任务
ansible test -m cron -a ' minute="*/10" job="/bin/echo hello" name="test" state="present" '
报错:
192.168.1.47 | FAILED! => {
"changed": false,
"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
}
解决方法:
install libselinux-python -y
删除定时任务
ansible test -m cron -a ' minute="*/10" job="/bin/echo hello" name="test" state="absent" '
5. user模块
创建用户 ansible test -m user -a 'name=user1' --sudo ansible test -m user -a 'name=user1' -s
删除用户 ansible test -m user -a 'name=user1 state=absent' --sudo ansible test -m user -a 'name=user1 state=absent' -s
6. group模块
创建组 ansible test -m group -a 'name=mysql gid=306 system=yes' --sudo
删除组 ansible test -m group -a 'name=mysql gid=306 system=yes state=absent' --sudo
7. copy模块
复制文件
ansible test -m copy -a 'src=/home/zhangshaohua1510/201811-11url-path.txt dest=/tmp owner=root mode=640' --sudo
复制目录
ansible test -m copy -a 'src=/home/zhangshaohua1510/ dest=/tmp/test owner=root mode=640' --sudo
复制内容到某个文件
ansible test -m copy -a 'content='hello' dest=/tmp/a.txt' --sudo
8. file模块
设定文件软链接
ansible test -m file -a 'path=/tmp/b.txt src=/tmp/a.txt state=link' --sudo
9. ping模块
ansible test -m ping
10. service模块
ansible test -m service -a 'enabled=true name=salt-minion state=stopped' --sudo
11. shell模块
ansible test -m shell -a 'echo yangjianbo >/tmp/c.txt' --sudo
12. script模块
ansible test -m script -a '/home/zhangshaohua1510/useradd.sh' --sudo
13. yum模块
ansible test -m yum -a 'name=httpd state=present enabled=yes' --sudo 安装httpd
ansible test -m service -a 'enabled=true name=httpd state=started' --sudo 启动httpd服务
ansible test -m service -a 'enabled=false name=httpd state=stopped' --sudo 关闭httpd服务
ansible test -m yum -a 'name=httpd state=absent' --sudo
14. setup模块
ansible test -m setup 收集远程主机的facts信息
15. unarchive模块
- name: tar tomcat.gz
unarchive: src=/tmp/apache-tomcat-8.5.43.tar.gz dest=/tmp copy=no
16. 列出某个组的所有主机
ansible test --list
ansible test --list-hosts
4. 特定主机变更
1. --limit
ansible test -m ping --limit 192.168.1.100
2. 指定IP
ansible 192.168.1.100 -m ping
3. 用冒号作分配符
5. 用户与组管理
1. linux用户管理
使用user模块
1. 创建用户
ansible test -m user -a "name=dba shell=/bin/bash groups=admin,dbagroup append=yes home=/home/dba state=present"
2. 修改用户属组
ansible test -m user -a "name=dba shell=/bin/bash groups=dbagroup,dbagroup append=no"
3. 修改用户属性
ansible test -m user -a "name=dba expire=1464775200"
4. 删除用户
ansible test -m user -a "name=user1 state=absent remove=yes"
5. 变更用户密码
2. windows用户管理
使用win_user模块
ansible test -m user -a "name=user1 passwd=123 group=administrators"
3. 应用层用户管理
使用mysql_user模块
ansible test -m mysql_user -a 'login_host=localhost login_password=123 login_user=root name=yang password=123456 priv=zabbix.*:ALL state=present'
4. 构建playbook
1. 使用yaml文件
2. 限定执行范围
ansible-playbook a.yml --limit webservers
ansible-playbook a.yml --list-hosts 列出受影响的主机,但是不会执行任何命令
3. 用户与权限设置
1. --remote-user
获取用户的顺序,查找playbook的hosts字段定义users----Inventory文件中定义的用户----默认使用当前系统用户来连接远程主机
也可以在命令行加入参数--remote-user
ansible-playbook a.yml --remote-user=yang
2. --ask-sudo-pass(-K) 传递sudo用户的密码到远程主机
3. --sudo 强制所有play都使用sudo用户
4. --sudo-user 使用哪个sudo用户
5. 当前用户tom使用jerry用户运行playbook
ansible-playbook a.yml --sudo --sudo-user=jerry --ask-sudo-pass
4. 创建一个playbook实例
1. 实例一:创建nginx组和用户
- hosts: test
remote_user: root
tasks:
- name: create nginx group
group: name=nginx system=yes gid=200
- name: create nginx user
user: name=nginx uid=208 group=nginx system=yes
执行这个playbook
ansible-playbook useradd.yml
2. 实例二:拷贝文件到指定目录
- hosts: test
remote_user: root
tasks:
- name: copy file to test
copy: src=/home/zhangshaohua1510/useradd.yml dest=/home/zhangshaohua1510/
ansible-playbook copyfile.yml
5. handlers的使用
用于关注的资源发生变化时,采取一定的操作。
1. 实例一:安装配置httpd
- hosts: test
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: installed configure file for httpd
copy: src=/home/zhangshaohua1510/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: start httpd service
service: enabled=true name=httpd state=started
报错:
解决方法:
修改ansible的配置文件/etc/ansible/ansible.cfg。
[privilege_escalation] ##这一部分为提升权限的参数,如果使用普通用户需要开启。
become=True
become_method=sudo
become_user=root
become_ask_pass=False
说明:第一个任务安装httpd,即使多次执行playbook,第一个任务完成后,都不会再被执行。
第二个任务copy配置文件。
第三个任务启动httpd服务。
2. 实例二:还是在实例一的基础上,我要求修改httpd的配置,然后重启httpd服务。
- hosts: test
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: installed configure file for httpd
copy: src=/home/zhangshaohua1510/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restarted httpd
- name: start httpd service
service: enabled=true name=httpd state=started
handlers:
- name: restarted httpd
service: name=httpd state=restarted
6. 变量
1. 命令行的方式定义变量
ansible-playbook a.yaml --extra-vars "foo=bar"
ansible-playbook a.yaml --extra-vars "@b.yaml" 将定义变量的写入一个文件中,然后调用这个文件
2. 在playbook中,yml定义变量,引用变量的时候需要使用两个{{ 变量名 }}
- hosts: test
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{ package }} state=latest
- name: installed configure file for httpd
copy: src=/home/zhangshaohua1510/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restarted httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
handlers:
- name: restarted httpd
service: name={{ service }} state=restarted
3. 可以引用ansible中所有的变量。
- hosts: test
remote_user: root
tasks:
- name: copy file
copy: content="{{ ansible_all_ipv4_addresses }}" dest=/tmp/var.ansible
4. 在/etc/ansible/hosts中添加变量,这就是主机变量;也可以使用组变量。
[test]
192.168.1.47 testvars='a'
[test:vars]
testvars='b'
引用方式:
- hosts: test
remote_user: root
tasks:
- name: copy file
copy: content="{{ ansible_all_ipv4_addresses }},{{ testvars }}" dest=/tmp/var.ansible
也可以在/etc/ansible/host_vars目录中创建与主机名相同的文件,使用yaml语法来定义所需的变量
也可以在/etc/ansible/group_vars目录中创建与组名相同的文件,使用yaml语法来定义所需的变量
5. 变量的定义也可以在一个独立的文件中完成
- hosts: test
vars_files:
- vars.yml
remote_user: root
tasks:
- name: copy file
copy: content="{{ ansible_all_ipv4_addresses }},{{ testvars }}" dest=/tmp/var.ansible
定义变量的独立文件vars.yml的内容如下:
testvars: yang
6. 注册变量
7. Facts变量
8. 变量优先级
1. 命令行中定义的变量
2. 在Inventory中定义的连接变量
3. 大多数的其它变量
4. 在Inventory定义的其它变量
5. 系统发现的facts
6. role默认变量
7. 流程控制
1. 变量注册器register
- shell: my_command_here
register: my_command_result
标准输出: my_command_result.stdout
错误输出: my_command_result.stderr
2. when条件判断
- hosts: all
remote_user: root
vars:
- username: yangjianbo
tasks:
- name: create {{ username }} user
user: name={{username}}
when: ansible_fqdn=="192168147"
3. when与注册变量结合使用
- command: my-app --status
register: myapp_result
- command: do-something-to-my-app
when: " 'ready' in myapp_result.stdout "
4. changed_when,failed_when条件判断
- command: my-app --status
register: myapp_result
- command: do-something-to-my-app
changed_when: " 'ready' in myapp_result.stdout "
- command: my-app --status
register: myapp_result
- command: do-something-to-my-app
failed_when: " 'ready' in myapp_result.stdout "
5. ignore_errors条件判断
ignore_errors: true
8. 任务间流程控制
1. 任务委托 (使用delegate_to关键字配置任务在指定的机器上,而hosts指向的是整个webservers)
- hosts: webservers
tasks:
- name: add server
command: 要执行的命令
delegate_to: "具体的某个机器"
2. 任务暂停
delay选项来指定timeout时间内进行检测的时间间隔,时间单位为秒
9. 交互式提示
10. tags标签
给某个task定义tags,只运行这个task.
- hosts: test
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{ package }} state=latest
- name: installed configure file for httpd
template: src=/home/zhangshaohua1510/templates/httpd.conf dest=/etc/httpd/conf/httpd.conf
tags:
- conf
notify:
- restarted httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
handlers:
- name: restarted httpd
service: name={{ service }} state=restarted
执行这个playbook,ansible-playbook httpd.yml --tags="conf" 。
注意:特殊的tags,
tags:
- always
忽略某个标签的任务,使用--skip-tags选项
11. block块
块功能可以将任务进行分组,并且可以在块级别上应用任务变量
5. Playbook高级用法
1. 巧用Includes
1. 语法
把一个任务切割成为多个任务,通过使用Includes调用。
- include: test.yml
2. 动态Includes
与register变量和when结合使用
connect设置在ansible的控制台机器上执行,而并不会在远程主机上执行
3. Handler Includes使用
Ansible Handler结合Notify用于当资源状态发生变化时一次性地执行指定操作。
在tasks目录下,有多个任务,其中reload.yml是用来发起通知,调用handlers目录下的main.yml
这是tasks的reload.yml
- name: cp vhost to tengine
copy: src=website/{{ domain }}/vhost dest=/usr/local/nginx/conf/
tags:
- vhost_conf
notify:
- reload nginx
这是handlers目录下的main.yml文件
- name: reload nginx
shell: /usr/local/nginx/sbin/nginx -s reload
2. 巧用Roles
1. 构建Roles
1. Roles主要依赖于目录的命名和摆放,默认tasks/main.yml是所有任务的入口
2. Roles不仅支持tasks的集合,同时包括vars_files,tasks,handlers,meta,templates
3. 每个目录下均由main.yml定义该功能的任务集,tasks/main.yml默认执行所有指定的任务。
4. Roles的调用文件playbook_role.yml的内容,roles目录默认放在/etc/ansible/roles,调用文件与roles目录在同一级目录下
- hosts: all ####这个是hosts定义个主机组名字,如果是单台主机可以直接写地址
serial: "50%"
remote_user: java ####执行用户
roles: #####解释配置文件目录,因为我们这次装的是tomcat所以注释其他的
- deploy_tomcat8
2. 使用Roles重构playbooks
1. group_vars目录下的文件定义Roles中调用的变量,group_vars目录下的文件名称要与hosts的组名一致,才能被该组的主机引用变量,文件名为all的针对主机引用的变量
2. user-config.yml文件,用来调用Roles的git模块
- hosts: localhost
remote_user: root
roles:
- role: git
- role: user
3. roles/git/tasks/main.yml文件,设置调用git模块实现的功能
- include: create_dir.yml
- include: static_git_pull.yml
- include: git_checkout.yml
3. 功能齐全的roles
1. 各个功能集的含义
roles/x/tasks/main.yml 主函数,包括在其中的所有任务将被执行
roles/x/handlers/main.yml 所有包括其中的handlers将被执行
roles/x/vars/main.yml 所有包括在其中的变量将在roles中生效
roles/x/meta/main.yml roles所有依赖将被正常导入
roles/x/files/ 存储由copy或者script等模块调用的文件
roles/x/templates 存储由template模块调用的模板文本
roles/x/defaults/main.yml 用于设定默认变量
2. 当Apache的配置文件发生变化时重启Apache进程,handler使用
1. 编排Roles目录结构
2. handlers的main.yml内容
3. task的restart.yml内容
4. task的main.yml内容
5. 同roles目录同一级的调用apache.yml文件内容
6. 执行命令
ansible-playbook apache.yml
3. Roles之文件传输
Files目录下的文件无需写绝对路径即可将文件传输至远程主机
1. 编排目录结构
2. tasks的文件内容
file.yml内容
main.yml内容
3. 调用文件file.yml,并执行命令ansible-playbook file.yml
4. Roles之Templates
1. 编排目录
2. 调用文件template.yml
3. 编辑tasks文件
main.yml文件
template.yml文件
4. 定义模板文件
5. 定义变量
6. 执行命令
ansible-playbook template.yml
7. 其它例子
1. 把配置文件制作成一个jinja文件。也就是在配置文件中使用变量。
例如:
Listen 80修改成: Listen {{http_port}}
2. 需要roles/x/vars里面,添加变量与值
3. 修改playbook文件中的内容:
- hosts: test
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{ package }} state=latest
- name: installed configure file for httpd
template: src=/home/zhangshaohua1510/templates/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restarted httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
handlers:
- name: restarted httpd
service: name={{ service }} state=restarted
3. Jinja2实现模板
1. jinja2 for循环
1. 基本语法
{% for item in all_items %}
{{ item }}
{% endfor %}
2. 例子
2. jinja2 if条件
1. 基本语法
{% if my_conditional %}
...
{% endif %}
2. 例子
1. 编排目录结构
2. 配置mysqlconf.yml
3. 配置模板文件
4. 执行命令,看一下结果
3. Jinja多值合并
1. 例子
1. 模板内容
2. join.yml内容
3. 执行命令ansible-playbook join.yml,结果如下:
4. Jinja default()设定
1. 例子
5. Ansible结合jinja2生成nginx配置
1. 编排目录
2.
6. 在playbook中使用迭代
当需要重复执行任务的时候,可以使用迭代机制。
- hosts: all
remote_user: root
tasks:
- name: create user
user: name={{item}} state=present
with_items:
- user1
- user2
或者
- hosts: all
remote_user: root
tasks:
- name: create user
user: name={{item.name}} state=present groups={{item.groups}}
with_items:
- {name: 'test1',groups: 'yunwei'}
- {name: 'test2',groups: 'root'}
13. 使用ansible部署一台tomcat服务器
1. 目录结构如下:
2. /etc/ansible/web.yml
- hosts: testhost ####这个是hosts定义个主机组名字,如果是单台主机可以直接写地址
remote_user: root ####执行用户
roles: #####解释配置文件目录,因为我们这次装的是tomcat所以注释其他的
# - nginx
# - mysql
- tomcat
# - db
3. /etc/ansible/roles/tomcat/tasks/main.yml
#创建用户
- name: group
group: name=java gid=507
- name: user
user: name=java group=java uid=507 password='$1$java$2F85crPl61NUQq5qiCTFD1'
##############################这个源码包安装JDK#############################
#复制jdk到tmp目录下
- name: copy jdk-7u60-linux-x64.rpm
copy: src=jdk-7u60-linux-x64.rpm dest=/tmp/jdk-7u60-linux-x64.rpm
- name: install jdk
command: /bin/rpm -ivh /tmp/jdk-7u60-linux-x64.rpm
ignore_errors: True
##########################安装tomcat###########################################
- name: copy tomcat
copy: src=apache-tomcat-7.0.53.server.noi.tar dest=/tmp/apache-tomcat-7.0.53.server.noi.tar
- name: install tomcat
shell: /bin/tar xf /tmp/apache-tomcat-7.0.53.server.noi.tar -C /tmp && /bin/mv /tmp/apache-tomcat-7.0.53 /usr/local/tomcat-zpapi
4. 另外一个脚本
- name: stop tomcat
shell: /usr/local/tomcat-{{tomcat_name}}/bin/catalina.sh stop
ignore_errors: True
tags: t1
- name: ps -ef | grep tomcat-{{tomcat_name}}
shell: ps -ef | grep tomcat-{{tomcat_name}} | grep 'bin/java' | grep -v grep
register: returnmsg
ignore_errors: True
tags: t6
- name: stop tomcat-{{tomcat_name}} successful
debug:
msg: "stop tomcat-{{tomcat_name}} successful"
when: returnmsg.rc == 1
tags: t7
- name: kill -9 tomcat-{{tomcat_name}}
shell: /bin/kill -9 `ps -ef | grep tomcat-{{tomcat_name}} | grep 'bin/java' |grep -v grep | awk '{print $2}'`
when: returnmsg.rc == 0
tags: t8
- name: list /usr/local/tomcat-{{tomcat_name}}/webapps
shell: ls
args:
chdir: /usr/local/tomcat-{{tomcat_name}}/webapps
register: files_list
tags: t2
- name: clean the directory
file:
path: /usr/local/tomcat-{{tomcat_name}}/webapps/{{item}}
state: absent
with_items:
- "{{ files_list.stdout_lines }}"
tags: t3
- name: copy war to webapps
copy:
src=/home/java/war/online/{{tomcat_name}}/{{tomcat_name}}.war
dest=/usr/local/tomcat-{{tomcat_name}}/webapps/
owner=java
tags: t4
- name: start tomcat
shell: chdir=/usr/local/tomcat-{{tomcat_name}}/bin nohup ./catalina.sh start
tags: t5
14. 使用ansible部署一台nginx服务器
15. 使用ansible部署一台mysql服务器
16. 使用ansible部署一台zabbix客户端
- name: copy zabbix_agent
copy: src=zabbix-2.2.2.tar.gz dest=/tmp/
- name: tar zabbix_agent
unarchive: src=/tmp/zabbix-2.2.2.tar.gz dest=/tmp copy=no
- name: yum
yum: name=gcc,openssl-devel,pcre-devel,zlib-devel state=latest
- name: create zabbix group
group: name=zabbix gid=1501 system=yes
- name: create zabbix user
user: name=zabbix uid=1501 group=zabbix shell=/sbin/nologin
- name: copy install.sh
copy: src=install_zabbix_agent.sh dest=/tmp/
- name: install zabbix_agent
shell: /bin/bash /tmp/install_zabbix_agent.sh
- name: copy zabbix_agentd
copy: src=zabbix_agentd dest=/etc/init.d/ mode=755
- name: copy zabbix_agentd.conf
template: src=/etc/ansible/roles/zabbix_agent/templates/zabbix_agentd.conf.j2 dest=/usr/local/zabbix/etc/zabbix_agentd.conf
- name: copy tcp_status disk_status
copy:
src: '{{ item.src }}'
dest: '{{ item.dest }}'
mode: 0755
with_items:
- { src: 'tcp_status.conf', dest: '/usr/local/zabbix/etc/zabbix_agentd.conf.d/' }
- { src: 'tcp_status.sh', dest: '/usr/local/zabbix/etc/zabbix_agentd.conf.d/' }
- { src: 'disk_status.conf', dest: '/usr/local/zabbix/etc/zabbix_agentd.conf.d/' }
- { src: 'disk_status.sh', dest: '/usr/local/zabbix/etc/zabbix_agentd.conf.d/' }
- name: del dir
file:
path: '{{ item }}'
state: absent
with_items:
- /usr/local/zabbix/etc/zabbix_agent.conf
- /usr/local/zabbix/etc/zabbix_agent.conf.d
- name: start zabbix_agent
shell: /etc/init.d/zabbix_agentd start
- name: add zabbix_agentd_service
shell: chkconfig zabbix_agentd on
17. 使用ansible部署ELK节点
18. 使用ansible部署filebeat
19. 使用ansible部署haproxy服务器
20. 使用ansible部署keepalive
21. 使用ansible部署redis
22. ansible启用日志
1. 打开/etc/ansible/ansible.cfg中,log_path = /var/log/ansible.log,这一行。
2. 手工创建touch /var/log/ansible.log,并授权sudo chown zhangshaohua1510:zhangshaohua1510 /var/log/ansible.log\
23. ansible常见问题
1. 执行命令的时候报错,如下:
[zhangshaohua1510@elk-node-3 ~]$ ansible testhost -m ping
192.168.1.189 | UNREACHABLE! => {
"changed": false,
"msg": "[Errno 111] Connection refused",
"unreachable": true
}
解决方法:
ansible的配置文件中的端口不对,默认用的22,修改为11984.
2. 执行命令的时候报错,如下:
atal: [192.168.2.51]: UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_request_forwards: requesting forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 31395\r\ndebug3: mux_client_request_session: session request sent\r\ndebug1: mux_client_request_session: master session id: 5\r\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Control master terminated unexpectedly",
"unreachable": true
}
解决方法:登录目标端,将对应的ssh进程杀掉,即可。
一往无前虎山行,拨开云雾见光明