Ansible自动化运维Inventory与Ad-Hoc

前言

自动化运维是指利用自动化工具和技术来简化、自动化和优化IT基础设施的管理和运维过程,从而提高效率、降低成本,并减少人为错误。在当今复杂的IT环境中,自动化运维已经成为许多组织和企业提高生产力和保证系统稳定性的重要手段。Ansible作为一种自动化运维工具,在这样的背景下应运而生,它通过简单、灵活的方式实现了IT基础设施的自动化管理。

目录

前言

一、Ansible 介绍

1. 概述

2. 组成

3. 工作原理

4. 特性

二、Install 部署

1. 环境准备

2. 安装 ansible

3. 相关文件

4. ansible 主配置文件

5. 免密管理 ssh-keygen

三、Ansible基础 

1. 定义主机清单

2. 测试连通性

3. 简洁输出

4. know_hosts

5. ping和ssh

四、Inventory 主机清单

1. 简介

2. 增加主机组

3. 增加用户名密码

4. 增加端口

5. 组:变量

6. 子分组

7. 自定义主机列表

五、Ad-Hoc 点对点模式

1. 简介

2. 模块

2.1 command 模块

2.2 shell 模块

2.3 script 模块

2.4 copy 模块

2.5 get_url 模块 

2.6 fetch 模块

2.7 file 模块

2.8 stat 模块

2.9 unarchive 模块

2.10 archive 模块

2.11 hostname 模块

2.12 cron 模块

2.13 yum 和 apt 模块  

2.14 yum_repository 模块

2.15 service 模块

2.16 mount 挂载和卸载

2.17 user 模块

2.18 group 模块

2.19 reboot模块

2.20 lineinfile 模块

2.21 replace 模

2.22 setup 模块


一、Ansible 介绍

1. 概述

Ansible基于Python开发,结合了众多运维工具的优点,最终实现批量系统配置、批量程序部署以及批量运行命令等功能。

2. 组成

  • INVENTORY:Ansible管理主机的清单 /etc/anaible/hosts 需要管理的服务清单
  • MODULES:Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
  • PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
  • API:供第三方程序调用的应用程序编程接口

3. 工作原理

Ansible基于模块化工作,本身没有批量部署的能力,真正具有批量部署的是Ansible所运行的模块(Modules)。Ansible只是提供了一种框架,在Ansible管理体系中,存在着管理节点Control Node)和被管理节点(Managed Node)两种角色。被管理节点通常称之为资产,会放在主机清单(Inventory)文件中,Inventory其实就是由Ansible所管理的主机形成的。在管理节点上,Ansible将Ad-Hoc(批量执行单条命令,即单模块)或者Playbook(任务剧本)转化为Python脚本,最终通过ssh网络协议将这些Python脚本传递到被管理节点,在被管理服务器上依次执行,并且会实时将结果返回给管理节点。返回结果顺序根据网络、被管理服务器本身性能等因素有关。

① 管理节点(Control Node):在控制节点上安装Ansible,并使用Ansible的命令行工具或者其他接口来编写和执行自动化任务。

② 主机清单(Inventory):控制节点上维护一个主机清单文件,列出了需要管理的目标主机的信息,包括IP地址、主机名等。

③ 任务剧本(Playbook):Playbook通常是josn格式的YAML文件,定义了一系列任务和配置信息,用于描述自动化任务的执行流程。Playbook编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,相当于多个Ad-Hoc的配置文件。

④ 单模块(AD-Hoc):指的是在不使用Playbook的情况下,直接使用ansible命令行工具执行临时命令。这些命令通常是一次性的、针对特定任务的,而不需要编写长期维护的Playbook。通过AD-Hoc命令,可以快速地在远程主机上执行特定的任务,比如文件操作、软件安装、服务管理等。

⑤ 执行任务模块(Modules): Ansible提供了丰富的模块,用于执行各种管理任务,比如文件操作、软件包管理、服务管理等。

⑥ Python:在Ansible中,默认情况下,Ansible会利用目标主机上已安装的Python解释器来执行远程命令。Ansible的核心引擎和大部分模块都是基于Python编写的,因此要求目标主机上必须安装有Python(通常是2.6版本或以上)才能正常运行Ansible管理任务。

⑦ SSH连接:Ansible使用SSH协议来连接目标主机,并在目标主机上执行任务。

⑧ 被管理节点(Managed Node):是指由Ansible进行配置、管理和自动化操作的远程主机或设备。这些被管理节点是Ansible控制节点所管理的目标系统,可以是服务器、虚拟机、网络设备或其他类型的计算设备。 

4. 特性

① 模块化:调用特定的模块完成特定任务,支持自定义模块,可使用任何编程语言写模块(账号,软件等)

② Paramiko(python对ssh的实现),PyYAML,Jinja2(模板语言)三个关键模块

③ 基于Python语言实现

④ 部署简单,基于python和SSH(默认已安装),agentless,无需代理不依赖PKI(无需ssl)

⑤ 安全,基于OpenSSH

⑥ 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况,此特性非绝对

⑦ 支持playbook编排任务,YAML格式,编排任务,支持丰富的数据结构

⑧ 较强大的多层解决方案 role

二、Install 部署

1. 环境准备

① 设备准备(均关闭防火墙、核心防护)

ansible服务器:192.168.190.100

ansible客户机:192.168.190.101、192.168.190.102、192.168.190.103、192.168.190.104

② ansible服务器添加域名解析,客户机无需配置

[root@localhost ~]# vim /etc/hosts
192.168.190.100 ansible
192.168.190.101 host1
192.168.190.102 host2
192.168.190.103 host3
192.168.190.104 host4

2. 安装 ansible

① 配置阿里云yum源,本机已存在可以忽略

[root@localhost ~]# cd /etc/yum.repos.d/
[root@localhost yum.repos.d]# mkdir bak;mv *.repo bak
[root@localhost yum.repos.d]# vim CentOS-Base.repo
[base]
name=CentOS-$releasever - Base - aliyun
baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
gpgcheck=0
enabled=1

[updates]
name=CentOS-$releasever - Updates - aliyun
baseurl=http://mirrors.aliyun.com/centos/$releasever/updates/$basearch/
gpgcheck=0
enabled=1

[extras]
name=CentOS-$releasever - Extras - aliyun
baseurl=http://mirrors.aliyun.com/centos/$releasever/extras/$basearch/
gpgcheck=0
enabled=1

[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
baseurl=https://mirrors.aliyun.com/epel/7/$basearch
failovermethod=priority
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

[root@localhost yum.repos.d]# ls
bak  CentOS-Base.repo
[root@localhost yum.repos.d]# yum clean all
[root@localhost yum.repos.d]# yum makecache

② Install安装

[root@localhost ~]# yum install ansible -y
已安装:
  ansible.noarch 0:2.9.27-1.el7                                                                                  

作为依赖被安装:
  PyYAML.x86_64 0:3.10-11.el7                             libyaml.x86_64 0:0.1.4-11.el7_0                       
  python-babel.noarch 0:0.9.6-8.el7                       python-jinja2.noarch 0:2.7.2-4.el7                    
  python-markupsafe.x86_64 0:0.11-10.el7                  python-paramiko.noarch 0:2.1.1-9.el7                  
  python2-httplib2.noarch 0:0.18.1-3.el7                  python2-jmespath.noarch 0:0.9.4-2.el7                 
  sshpass.x86_64 0:1.06-2.el7 

[root@localhost ~]# rpm -qc ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts

③ 查看基本信息

[root@localhost ~]# ansible --version
ansible 2.9.27
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]

3. 相关文件

  • /etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性,也可以在项目的目录中创建此文件,当前目录下如果也有ansible.cfg,则此文件优先生效,建议每个项目目录下,创建独有的ansible.cfg文件
  • /etc/ansible/hosts 主机清单
  • /etc/ansible/roles/ 存放角色的目录

4. ansible 主配置文件

Ansible 的默认配置文件路径:/etc/ansible/ansible.cfg

[defaults]
#inventory     = /etc/ansible/hosts 	#主机列表配置文件
#library = /usr/share/my_modules/ 		#库文件存放目录
#remote_tmp = $HOME/.ansible/tmp 		#临时py命令文件存放在远程主机目录
#local_tmp     = $HOME/.ansible/tmp 	#本机的临时命令执行目录
#forks         = 5   					#默认并发数
#sudo_user     = root 					#默认sudo 用户
#ask_sudo_pass = True 					#每次执行ansible命令是否询问ssh密码
#ask_pass      = True                   #当连接到远程主机时,会提示用户输入SSH密码
#remote_port   = 22                     #连接到远程主机时所使用的SSH端口号。默认为22。
#host_key_checking = False     			#检查对应服务器的host_key,建议取消此行注释,实现第一次连接自动信任目标主机
#log_path=/var/log/ansible.log 			#日志文件,建议启用
#module_name = command   				#默认模块,可以修改为shell模块
[privilege_escalation] 					#普通用户提权配置
#become=True
#become_method=sudo
#become_user=root
#become_ask_pass=False

5. 免密管理 ssh-keygen

用于生成SSH密钥对的命令行工具。它通常用于创建公钥和私钥,以便进行安全的SSH通信。

[root@localhost ~]# ssh-keygen   #一直按回车
[root@localhost ~]# ls .ssh/
id_rsa  id_rsa.pub
[root@localhost ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.190.101 #推送公钥给host1

[root@localhost ~]# ssh root@192.168.190.101
Last login: Wed Mar 13 14:04:13 2024 from 192.168.190.1
[root@localhost ~]# ifconfig ens33 | grep netmask | awk "{print \$2}"
192.168.190.101

三、Ansible基础 

1. 定义主机清单

[root@localhost ~]# vim /etc/ansible/hosts
host1
host2
host3
host4

2. 测试连通性

① 测试本机

[root@localhost ~]# ansible localhost -m ping
localhost | SUCCESS => {                        #绿色字体
    "changed": false, 
    "ping": "pong"
}

② 分别测试host1和host2,此时host1做了免密登录,观察返回信息

[root@localhost ~]# ansible host1 -m ping
Are you sure you want to continue connecting (yes/no)? yes
host1 | SUCCESS => {                                        #绿色字体
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[root@localhost ~]# ansible host2 -m ping
Are you sure you want to continue connecting (yes/no)? yes
host2 | UNREACHABLE! => {                                   #红色字体
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: Warning: Permanently added 'host2,192.168.190.102' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", 
    "unreachable": true
}

3. 简洁输出

[root@localhost ~]# ansible host1 -m ping -o
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
#绿色字体

4. know_hosts

[root@localhost ~]# ansible host2 -m ping -o -u root -k  #指定用户交互式ssh登录
SSH password: 
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
#绿色字体

关闭ssh询问

方法一:修改sshd配置,StrictHostKeyChecking no

[root@localhost ~]# vim /etc/ssh/ssh_config
 35 #   StrictHostKeyChecking ask
 36     StrictHostKeyChecking no
[root@localhost ~]# systemctl restart sshd

 方法二:修改ansible配置,启用host_key_checking = False

[root@localhost ~]# vim /etc/ansible/ansible.cfg
71 host_key_checking = False

5. ping和ssh

Ping 是一种基于 ICMP(Internet Control Message Protocol)的网络工具,通常用于测试两台计算机之间的连接和延迟。通过发送 ICMP 回显请求消息到目标主机并等待其回应,可以确定目标主机是否可达以及网络延迟情况。

SSH(Secure Shell)是一种加密的网络协议,用于安全地远程连接到另一台计算机,并在该计算机上执行命令。SSH 提供了加密的通信渠道,使得数据传输过程中更加安全,并且还允许用户进行身份验证,确保只有授权用户能够访问远程计算机。

区别:
协议类型:

  • Ping 使用 ICMP 协议,用于检测主机之间的连通性。
  • SSH 使用安全的加密通信协议,用于远程登录和执行命令。

功能:

  • Ping 用于测试主机之间的连通性和延迟。
  • SSH 用于建立安全的远程连接,允许用户登录并在远程主机上执行命令。

安全性:

  • Ping 不提供加密或身份验证,仅用于测试连接。
  • SSH 提供加密通信和身份验证,确保通信的安全性和用户身份的合法性

四、Inventory 主机清单

1. 简介

Inventory 主机清单是 Ansible 的一个重要概念,它用于定义 Ansible 将要管理的主机、服务器或设备。这个清单可以包含主机名、IP 地址、主机组以及其他相关的信息。

2. 增加主机组

[root@localhost ~]# vim /etc/ansible/hosts
[webserver]          #下方主机将被分配到webserver组中
host1
host2
host3
host4

[root@localhost ~]# ansible webserver -m ping -o
host3 | UNREACHABLE!: Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
host2 | UNREACHABLE!: Failed to connect to the host via ssh: Warning: Permanently added 'host2,192.168.190.102' (ECDSA) to the list of known hosts.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
host4 | UNREACHABLE!: Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
#由此可见webserver已经生效被调用,只有host1做了免密登录,返回结果可以忽略

3. 增加用户名密码

[root@localhost ~]# vim /etc/ansible/hosts 
[webserver]
host[1:4] ansible_ssh_user='root' ansible_ssh_pass='123'
[root@localhost ~]# ansible webserver -m ping -o
host3 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host4 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
#此时可以看到返回结果全部成功,且字体均为绿色;即使host1配置过免密,不冲突

4. 增加端口

① 修改host4 ssh协议端口号

[root@localhost ~]# vim /etc/ssh/sshd_config
 17 #Port 22
 18  Port 9527
[root@localhost ~]# systemctl restart sshd

② 测试ansible通信

[root@localhost ~]# ansible webserver -m ping -o
host4 | UNREACHABLE!: Failed to connect to the host via ssh: ssh: connect to host host4 port 22: Connection refused
host3 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
#此时host4无法通信,提示端口故障

 ③ 修改服务器Inventory主机清单配置,再次访问

[root@localhost ~]# vim /etc/ansible/hosts
[webserver]
host[1:3] ansible_ssh_user='root' ansible_ssh_pass='123'
host4     ansible_ssh_user='root' ansible_ssh_pass='123' ansible_ssh_port='9527'

[root@localhost ~]# ansible webserver -m ping -o
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host3 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host4 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
#可见全部成功

5. 组:变量

当一个组中需要大量定义变量,可以统一定义。定义完成后,改组的所有成员都将收到、适应这个变量。

[root@localhost ~]# vim /etc/ansible/hosts
[webserver]
host[1:3]
host4     ansible_ssh_port='9527'

[webserver:vars]
ansible_ssh_user='root'
ansible_ssh_pass='123'

[root@localhost ~]# ansible webserver -m ping -o
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host3 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host4 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
#全部返回成功

常用变量:

参数用途示例
ansible_ssh_host定义 hosts ssh 地址ansible_ssh_host=192.168.190.100
ansible_ssh_port定义 hosts ssh 端口ansible_ssh_port=9527
ansible_ssh_user定义 hosts ssh 认证用户ansible_ssh_user=root
ansible_ssh_pass定义 hosts ssh 认证密码ansible_ssh_pass=123
ansible_sudo定义 hosts sudo 用户ansible_sudo=zhangsan
ansible_sudo_pass定义 hosts sudo 密码ansible_sudo pass=123
ansible_sudo_exe定义 hosts sudo 路径ansible_sudo_exe=/usr/bin/sudo
ansible_connection定义 hosts 连接方式ansible_connection=local
ansible_ssh_private_ key_file定义 hosts 私钥ansible_ssh_private_key_file=/root/key
ansible_ssh_shell_ type定义 hosts shell 类型ansible_ssh_shell_type=bash
ansible_python_interpreter定义 hosts 任务执行python路径ansible_python_ interpreter=/usr/bin/python2.6
ansible_*_interpreter定义 hosts 其它语言解析路径ansible_*_interpreter=/usr/bin/ruby

6. 子分组

将不同的分组进行组合

[root@localhost ~]# vim /etc/ansible/hosts
[apache]
host[1:2]

[nginx]
host3
host4     ansible_ssh_port='9527'

[webserver:children]
apache
nginx

[webserver:vars]
ansible_ssh_user='root'
ansible_ssh_pass='123'

[root@localhost ~]# ansible webserver -m ping -o
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host3 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host4 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
#可见webserver这个总组调用了apache和nginx这两个从组

7. 自定义主机列表

打包主机清单,多处使用

将host4 ssh协议端口号改为默认22。

① 创建主机清单文件

[root@localhost ~]# vim /data/hostlist
[apache]
host[1:2]

[nginx]
host3
host4

[webserver:children]
apache
nginx

[webserver:vars]
ansible_ssh_user='root'
ansible_ssh_pass='123'

② 指定 Inventory 主机清单的位置,访问管理节点

[root@localhost ~]# ansible -i /data/hostlist webserver -m ping -o
host3 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host4 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
#访问成功,字体均为绿色

五、Ad-Hoc 点对点模式

1. 简介

指的是在不使用Playbook的情况下,直接使用ansible命令行工具执行临时命令。这些命令通常是一次性的、针对特定任务的,而不需要编写长期维护的Playbook。通过AD-Hoc命令,可以快速地在远程主机上执行特定的任务,比如文件操作、软件安装、服务管理等。

2. 模块

2.1 command 模块

command 模块允许用户在目标主机上执行特定的命令,主要功能是在远程主机执行命令,此为默认模块,可忽略 -m 选项;此命令不支持 $VARNAME < > | ; & 等,可能用shell模块实现 ;注意此模块不具有幂等性 。以下是 command 模块的一般用法:

ansible <host-pattern> -m command -a "<command>"
#<host-pattern> 是要操作的目标主机或主机组。
#-m command 指定要使用的模块是 "command"。
#-a "<command>" 传递给模块的参数,即要在目标主机上执行的命令。

示例: 复制文件至指定目录

如何修改默认模块?

[root@ansible ~]# vim /etc/ansible/ansible.cfg
114 #module_name = command

2.2 shell 模块

和command相似,用shell执行命令支持各种符号,比如:*,$, >,此模块不具有幂等性。

示例:创建文件hello.txt,写入内容hello

示例:提权操作

① 先在被控制端(host1)sudo授权

[root@localhost ~]# vim /etc/sudoers
 93 fql     ALL=(ALL)       NOPASSWD:ALL

② 以fql用户身份连接,然后以特权模式切换到fql用户,并执行whoami命令,查看当前登录用户

[root@ansible ~]# ansible host1 -m shell -a 'whoami' -u fql -k -b --become-user=fql
SSH password: 
[WARNING]: Module remote_tmp /home/fql/.ansible/tmp did not exist and was created with a mode of 0700, this may
cause issues when running as another user. To avoid this, create the remote_tmp dir with the correct permissions
manually
host1 | CHANGED | rc=0 >>
fql

2.3 script 模块

在远程主机上运行ansible服务器上的脚本(无需执行权限,本身不执行),此模块不具有幂等性。

示例:执行脚本新建hello文件

2.4 copy 模块

从ansible服务器主控端复制文件到远程主机,src=file 如果是没指明路径,则为当前目录或当前目录下的files目录下的file文件。关键字选项如下:

src       #代表源文件路径
dest      #代表文件落地路径
owner     #属主
group     #属组
mode      #代表权限
backup    #如果复制时有同名文件会先备份再复制(注意:源文件内容有变化才会备份)

准备:被管理节点新建用户fql

示例:拷贝管理节点文件至被管理节点指定目录,并指定属主及权限

注意:

  • etc不加/:连etc一起复制,etc会变成子目录
  • etc加/:只复制etc下的文件

2.5 get_url 模块 

用于将文件从http、https或ftp下载到被管理节点上。关键字选项如下:

url:     #下载文件的URL,支持HTTP,HTTPS或FTP协议
dest:    #下载到目标路径(绝对路径),如果目标是一个目录,就用服务器上面文件的名称,如果目标设置了名称就用目标设置的名称
owner:   #指定属主
group:   #指定属组
mode:    #指定权限
force:   #如果yes,dest不是目录,将每次下载文件,如果内容改变,替换文件。如果否,则只有在目标不存在时才会下载该文件
checksum:#对目标文件在下载后计算摘要,以确保其完整性(md5sum)
##可以检测文件是否有问题
[root@ansible ~]# md5sum nginx-1.18.0.tar.gz 
3ca4a37931e9fa301964b8ce889da8cb  nginx-1.8.0.tar.gz

[root@ansible ~]# ansible web -m get_url -a 'url=https://nginx.org/download/nginx-1.18.0.tar.gz dest=/opt checksum="md5:3ca4a37931e9fa301964b8ce889da8cb"'

示例:下载nginx源码包至被管理节点指定目录

2.6 fetch 模块

从远程主机提取文件至ansible的主控端,copy相反,目前不支持目录(可以将文件夹打包成压缩包传输)。

示例:拷贝被管理节点文件至服务端

2.7 file 模块

设置文件属性,创建软链接等,关键字选项如下:

path       #指定文件路径
state      #文件状态 有:新建(touch) 删除(absent) 文件夹(directory)  连接文件(link)等
src        #源文件
mode       #权限
owner      #属主
group      #属组
recurse    #递归,修改属性时有效

示例:

[root@ansible ~]# ansible web -m file -a 'path=/mnt/web.txt state=touch owner=fql group=fql mode=644'
#创建空文件
[root@ansible ~]# ansible web -m file -a 'path=/mnt/web state=directory'
#新建目录
[root@ansible ~]# ansible web -m file -a 'src=/mnt/web path=/opt/web-link state=link'
#新建软连接 path|dest|name   这三个选项都可以使用
[root@ansible ~]# ansible web -m file -a 'path=/opt/web-link state=absent'
#删除文件
[root@ansible ~]# ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql"
[root@ansible ~]# ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql recurse=yes"
#递归修改目录及子目录的属性

2.8 stat 模块

检查文件或文件系统的状态,对于Windows目标,请改用win_stat模块。

选项: 

  • path:文件/对象的完整路径(必须)

常用的返回值判断:

  • exists: 判断是否存在
  • isuid: 调用用户的ID与所有者ID是否匹配 

示例:判断文件是否存在

[root@ansible ~]# ansible webserver -m stat -a 'path=/opt/xxxxxx' -o
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "stat": {"exists": false}}
host3 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "stat": {"exists": false}}
host4 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "stat": {"exists": false}}
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "stat": {"exists": false}}
#不存在

2.9 unarchive 模块

解包解压缩。实现有两种用法:

  • 将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes,此为默认值,可省略
  • 将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no

常见参数:

copy:      #默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到被控制节点上,如果设置为copy=no,会在被控制节点上寻找src源文件
remote_src:#和copy功能一样且互斥,yes表示在被控制节点,不在ansible主机,no表示文件在ansible主机上
src:       #源路径,可以是ansible主机上的路径,也可以是远程主机(被管理端或者第三方主机)上的路径,如果是远程主机上的路径,则需要设置copy=no
dest:      #被控制节点的目标路径
mode:      #设置解压缩后的文件权限 

示例:将管理节点压缩包解压到被管理节点

① 管理节点创建(或指定现有)压缩包

[root@ansible data]# touch {1..3}.txt
[root@ansible data]# ls
1.txt  2.txt  3.txt
[root@ansible data]# tar -zcvf file.tar.gz 1.txt 2.txt 3.txt .
[root@ansible data]# ls
1.txt  2.txt  3.txt  file.tar.gz

②  将管理节点压缩包解压到被管理节点

示例:将被管理节点压缩包解压到被管理节点,即压缩包从被管理节点寻找

2.10 archive 模块

对被管理节点文件进行压缩,打包压缩保存在被管理节点。

参数:

path=/var/log/:        #指定要打包的目录路径为/var/log/。
dest=/data/log.tar.bz2:#指定创建的归档文件名为log.tar.bz2,并保存在/data/目录下。
format=bz2:            #指定归档文件的格式为bz2,即使用 bzip2 进行压缩。
owner=fql:             #指定归档文件的所有者为fql。
mode=0600:             #指定归档文件的权限模式为0600,即只有所有者具有读写权限,没有执行权限

示例:

2.11 hostname 模块

管理主机名,一般不使用此模块,主机名会一致。

示例:修改host1主机名

[root@ansible ~]# ansible host1 -m hostname -a 'name=node1'

2.12 cron 模块

用于管理 cron 作业(定时任务),支持时间:minute,hour,day,month,weekday。

功能、参数:

功能:
添加/删除 cron 作业: #可以使用 Ansible 的 cron 模块添加新的 cron 作业或删除现有的作业。
修改 cron 作业:      #可以更新现有的 cron 作业的时间表、命令等信息。
列出 cron 作业:      #可以列出系统中所有的 cron 作业,以便进行查看和管理。

参数:
name:        #cron 作业的名称。
minute/hour/day/month/weekday:  #cron 作业执行的时间表设定。
user:        #作业执行的用户。
job:         #要执行的命令或脚本。
state:       #指定作业的状态,可以是 present(存在)、absent(不存在)等。

示例:创建备份计划任务

示例:关闭计划任务

示例:删除计划任务

管理节点另外写法:ansible websrvs -m cron -a 'state=absent name=Synctime' 

2.13 yum 和 apt 模块  

yum管理软件包,只支持RHEL,CentOS,fedora,不支持Ubuntu其它版本

apt类似yum模块的功能,主要管理Debian相关版本的软件包

参数:

Yum 模块参数:
name:             #要安装、升级或删除的软件包名称。
state:            #指定软件包的状态,可以是 present(存在)、latest(最新)、absent(不存在)等。
update_cache:     #指定是否更新 Yum 软件包缓存。
disablerepo:      #禁用特定的 Yum 软件源。
enablerepo:       #启用特定的 Yum 软件源。
disable_gpg_check:#禁用 GPG 检查。
installroot:      #指定要安装软件包的根目录。
update_only:      #仅更新软件包而不安装新软件包。
conf_file:        #指定要使用的 Yum 配置文件。

apt 模块参数:
name:                  #要安装、升级或删除的软件包名称。
state:                 #指定软件包的状态,可以是 present(存在)、latest(最新)、absent(不存在)等。
update_cache:          #指定是否更新 apt 软件包缓存。
cache_valid_time:      #指定软件包缓存的有效时间。
force:                 #强制执行操作,即使可能有依赖关系问题。
allow_unauthenticated: #允许安装未经身份验证的软件包。
autoremove:            #自动删除不再需要的软件包。
purge:                 #卸载软件包并删除其配置文件。
upgrade:               #执行软件包升级操作。

示例:批量安装httpd

其他示例:

ansible websrvs -m yum -a 'name=nginx state=present enablerepo=epel'  #启用epel源进行安装
ansible websrvs -m yum -a 'name=* state=lastest exclude=kernel*,foo*' #升级除kernel和foo开头以外的所有包
ansible websrvs -m yum -a 'name=httpd state=absent'                   #删除

2.14 yum_repository 模块

用于管理 YUM 软件包管理器中的软件仓库配置的模块。它允许用户添加、删除和更新系统上的 YUM 软件仓库。

参数关键字:

name参数:			#必须参数,用于指定要操作的唯一的仓库ID,也就是”.repo”配置文件中每个仓库对应的”中括号”内的仓库ID。
baseurl参数:		#此参数用于设置 yum 仓库的 baseurl。
description参数:	#此参数用于设置仓库的注释信息,也就是”.repo”配置文件中每个仓库对应的”name字段”对应的内容。
file参数:			#此参数用于设置仓库的配置文件名称,即设置”.repo”配置文件的文件名前缀,在不使用此参数的情况下,默认以 name 参数的仓库ID作					  为”.repo”配置文件的文件名前缀,同一个”.repo” 配置文件中 可以存在多个 yum 源。
enabled参数:		#此参数用于设置是否激活对应的 yum 源,此参数默认值为 yes,表示启用对应的 yum 源,设置为 no 表示不启用对应的 yum 源。
gpgcheck参数:		#此参数用于设置是否开启 rpm 包验证功能,默认值为 no,表示不启用包验证,设置为 yes 表示开启包验证功能。
gpgcakey参数:		#当 gpgcheck 参数设置为 yes 时,需要使用此参数指定验证包所需的公钥。
state参数:		    #默认值为 present,当值设置为 absent 时,表示删除对应的 yum 源。

示例:批量新建yum仓库epel源

2.15 service 模块

管理系统服务状态的模块。它可以启动、停止、重新启动和重新加载系统服务。

参数关键字:

name参数:		#此参数用于指定需要操作的服务名称,比如 nginx。
state参数:	    #此参数用于指定服务的状态,比如,我们想要启动远程主机中的 nginx,则可以将 state 的值设置为 started;如果想要停止远程主机中的服务,则可以将 state 的值设置为 stopped。此参数的可用值有 started、stopped、restarted、reloaded。
enabled参数:	#此参数用于指定是否将服务设置为开机 启动项,设置为 yes 表示将对应服务设置为开机启动,设置为 no 表示不会开机启动。

示例:启动httpd服务并开机自启

2.16 mount 挂载和卸载

管理文件系统挂载和卸载的模块。它允许用户在远程主机上挂载和卸载文件系统,以及设置文件系统的相关属性。

主要参数:

path (必需): #要挂载或卸载的目标路径。
src:         #要挂载的设备、分区或者远程位置。
fstype:      #文件系统类型,例如 ext4、xfs 等。
state:       #可以是 mounted(已挂载)、unmounted(已卸载)或者 present(存在)。
opts:        #挂载选项,如 "rw"(读写)、"ro"(只读)等。
dump:        #控制备份程序是否应该备份文件系统。
passno:      #控制启动时文件系统检查的顺序。

示例:

#临时挂载
mount websrvs -m mount -a 'src="UUID=b3e48f45-f933-4c8e-a700-22a159ec9077" path=/home fstype=xfs opts=noatime state=present'
#临时取消挂载
mount websrvs -m mount -a 'path=/home fstype=xfs opts=noatime state=unmounted'
#永久挂载
ansible websrvs -m mount -a 'src=10.0.0.8:/data/wordpress path=/var/www/html/wp-content/uploads opts="_netdev" state=mounted'
#永久卸载
ansible websrvs -m mount -a 'src=10.0.0.8:/data/wordpress path=/var/www/html/wp-content/uploads state=absent'
#UUID为设备序列号,可以通过lsblk获得
[root@ansible ~]# ansible webserver -a "blkid"

2.17 user 模块

管理系统用户的模块。它允许用户创建、删除和修改系统用户以及相关属性。

主要参数:

comment         #用户的描述信息
createhome      #是否创建家目录
force           #在使用state=absent时, 行为与userdel –force一致.
group           #指定基本组(需要已存在的组)
groups          #指定附加组,如果指定为(groups=)表示删除所有组
home            #指定用户家目录
move_home       #如果设置为home=时, 试图将用户主目录移动到指定的目录
name            #指定用户名(必需)
non_unique      #该选项允许改变非唯一的用户ID值
password        #指定用户密码,使用 SHA512 hash
remove          #在使用state=absent时, 行为是与userdel –remove一致
shell           #指定默认shell
state           #设置帐号状态,不指定为创建,指定值为absent表示删除
system          #当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户
uid             #指定用户的uid
update_password   #用于控制何时更新用户的密码。该参数有三个可能的取值:
always:           #始终更新用户密码。
on_create:        #仅在创建用户时更新密码。
never:            #永远不更新密码。

示例:添加用户

示例:删除用户 

2.18 group 模块

管理系统用户组的模块。它允许用户创建、删除和修改系统用户组以及相关属性。

主要参数:

name (必需):  #要操作的用户组名称。
state:        #可以是 present(存在)、absent(不存在)。
gid:          #用户组的 GID。
system:       #如果为 true,则创建一个系统用户组。
append:       #如果为 true,则将用户添加到指定的用户组中;如果为 false,则只会将用户包含在指定的用户组中

示例:创建组

示例:删除组 

2.19 reboot模块

重启远程主机的模块。它允许用户在远程主机上执行重启操作。

主要参数:

msg:               #在执行重启操作之前向远程主机发送的消息。
pre_reboot_delay:  #在重启之前等待的时间。
post_reboot_delay: #在重启后等待的时间。
test_command:      #用于测试重启完成后系统是否可访问的命令。
confirm:           #指定是否需要在执行重启操作之前进行确认,默认为 false。

示例:重启被管理节点服务器

[root@ansible ~]#ansible websrvs -m reboot

2.20 lineinfile 模块

ansible在使用sed进行替换时,经常会遇到需要转义的问题,而且ansible在遇到特殊符号进行替换时,存在问题,无法正常进行替换。其实在ansible自身提供了两个模块:lineinfile模块和replace模块,可以方便的进行替换一般在ansible当中去修改某个文件的单行进行替换的时候需要使用lineinfile模块。
regexp参数 :使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除。
如果想进行多行匹配进行替换需要使用replace模块。

关键字参数:

path	        #指定要操作的文件
regexp	        #使用正则表达式匹配对应的行
line	        #修改为新的内容
insertafter	    #将文本插入到“指定的行”之后
insertbefore	#将文本插入到“指定的行”之前
state	        #删除对应的文本时,需要state=absent
backrefs	    # 1.支持后向引用、2.当未匹配到内容则不操作文件
backup	        #是否在修改文件之前对文件进行备份
create	        #当要操作的文件并不存在时,是否创建对应的文件

示例:

查找内容:
ansible web -m lineinfile -a "path=/etc/httpd/conf/httpd.conf regexp='^Listen' line='Listen 80'"
#修改apache监听端口

替换内容:
ansible all -m   lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=disabled'"
#关闭核心防护
ansible all -m lineinfile -a 'dest=/etc/fstab state=absent regexp="^#"'
#去掉#号

2.21 replace 模

该模块有点类似于sed命令,主要也是基于正则进行匹配和替换,建议使用。

示例:

ansible all -m replace -a "path=/etc/fstab regexp='^(UUID.*)' replace='#\1'"  
#给UUID开头行加上注释
ansible all -m replace -a "path=/etc/fstab regexp='^#(UUID.*)' replace='\1'"
#给#UUID开头行去掉注释
ansible web -m replace -a "path=/etc/httpd/conf/httpd.conf regexp='^Listen.*' line='Listen 80'"
#修改监听端口为80

2.22 setup 模块

收集有关远程主机的各种系统信息。这些信息包括操作系统类型、IP 地址、内存和 CPU 使用情况、磁盘空间以及许多其他有用的系统级信息。这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度。可以使用 gather_facts: no 来禁止 Ansible 收集 facts 信息。

常用参数:

gather_subset: #指定要收集的子集信息,例如all, network, hardware, virtual等。
gather_timeout:#设置收集信息的超时时间,以秒为单位。
filter:        #用于过滤输出信息,可以根据需要选择性地显示特定信息。
fact_path:     #指定一个目录,将收集到的信息保存为 JSON 文件。
retries:       #在发生连接问题时尝试重新连接的次数。

示例:禁止 Ansible 收集 facts 信息

[root@ansible ~]# ansible all -m setup -a "gather_facts:no"

以上内容就是Ansible主机清单和单模块使用的介绍,Ad-Hoc 命令是一次性的、即时执行的命令,当我们需要执行多个任务、配置复杂场景或需要可重复使用的操作应该如何处理?下篇介绍Ansible非标记语言YAML与任务剧本Playbook-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/457754.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

<JavaEE> 了解网络层协议 -- IP协议

目录 初识IP协议 什么是IP协议&#xff1f; IP协议中的基础概念 IP协议格式 图示 4bit版本号&#xff08;version&#xff09; 4bit头部长度&#xff08;headerlength&#xff09; 8bit服务类型&#xff08;TypeOfService&#xff09; 16bit总长度&#xff08;total l…

Chrome的V8引擎 和操作系统交互介绍

Chrome的V8引擎是一个用C编写的开源JavaScript和WebAssembly引擎&#xff0c;它被用于Chrome浏览器中&#xff0c;以解释和执行JavaScript代码。V8引擎将JavaScript代码转换为机器代码&#xff0c;这使得JavaScript能够以接近本地代码的速度运行。 V8引擎与操作系统的交互主要体…

开源免费CasaOS:轻松打造高效便捷的家庭云生活新体验

一、引言 随着科技的不断发展&#xff0c;家庭云系统逐渐成为现代家庭生活中的重要组成部分。CasaOS作为一款简单易用的开源家庭云系统&#xff0c;受到了广大用户的青睐。其简洁明了的界面设计&#xff0c;使得即使没有任何技术背景的用户也能轻松上手。本文将详细介绍CasaOS…

C# WPF编程-概述

C# WPF编程-基础知识 概述WPF高级API硬件加速与WPF分辨率无关性WPF体系结构WPF的主要类WPF工具包Visual Studio IDE 概述 WPF(Windows Presentation Foundation)是用于Windows的现代图形显示系统。引入了“内置硬件加速”和“分辨率无关”等创新功能。 WPF高级API 类似Web的…

【Docker】-- 使用docker部署Springboot+vue项目到虚拟机

虚拟机系统&#xff1a;CentOS 7 连接虚拟机工具&#xff1a;MobaXterm 以下在安装好虚拟机和docker基础上操作。 安装docker&#xff1a;【Docker】-- 如何安装docker-CSDN博客 一、部署Mysql 1、安装mysql docker中执行&#xff1a; docker run -d \--name mysql \-p 3…

Python + Jmeter 实现自动化性能压测

Step01: Python脚本开发 文件路径&#xff1a;D://wl//testproject//Fone-grpc//project1//test_client.py Python 脚本作用&#xff1a; 通过 grpc 调用底层 c 的接口&#xff0c;做数据库的数据插入与查询操作&#xff0c;然后将返回的结果进行拼接与输出。 2.代码里面将…

基于SpringBoot+MYSQL+Vue的校园管理系统

目录 1、前言介绍 2、主要技术 3、系统流程分析 3.1、操作流程 3.2、添加信息流程 3.3、删除信息流程 4、系统设计 4.1 系统体系结构 4.2开发流程设计 4.3 数据库设计原则 4.4 数据表 5、运行截图(部分) 5.1管理员功能模块 5.2用户功能模块 5.3院校管理员功能模块…

使用耳机壳UV树脂制作私模定制耳塞的价格如何呢?

耳机壳UV树脂制作私模定制耳塞的价格因多个因素而异&#xff0c;如材料、工艺、设计、定制复杂度等。 根据我目前所了解到的信息&#xff0c;使用UV树脂制作私模定制耳塞的价格可能在数百元至数千元不等。具体价格还需根据用户的需求和预算进行综合考虑。 如需获取更准确的报…

微信小程序仿QQ头像轮播效果

1、效果图 2、效果流程分析 1、第1个头像大小从1到0缩小的同时&#xff0c;第2个头像左移 2、上面动画结束后&#xff0c;延迟50ms&#xff0c;第3个头像从0到1放大 3、把头像列表顺序前移一位&#xff0c;并重置轮播状态&#xff0c;以此达到一个循环。然后继续第一个步骤 …

STL——map set

文章将解决一下几个问题&#xff1a; 1.什么是set 2.什么是map 3.set应用场景 4.map应用场景 序列式容器和关联式容器 数据结构有序列式容器和关联式容器&#xff0c;序列式容器一般有vector,list,deque…&#xff0c;但关联式容器中就有map&#xff0c;关联式容器也是用来存…

Java实现知乎热点小时榜爬虫

1.效果演示 1.1 热点问题列表 启动程序后&#xff0c;自动展示热点问题&#xff0c;并等待终端输入 1.2 根据序号选择想看的热点问题 输入问题序号&#xff0c;展示回答内容 1.3 退出 输入q即可退出程序 2.源码 2.1 pom.xml <?xml version"1.0" enco…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:FlowItem)

瀑布流组件的子组件&#xff0c;用来展示瀑布流具体item。 说明&#xff1a; 该组件从API Version 9开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。仅支持作为Waterflow组件的子组件使用。 子组件 支持单个子组件。 接口 FlowItem() 使…

[数据集][目标检测]零售柜零食检测数据集VOC+YOLO格式5422张113类

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;5422 标注数量(xml文件个数)&#xff1a;5422 标注数量(txt文件个数)&#xff1a;5422 标注…

html5cssjs代码 018颜色表

html5&css&js代码 018颜色表 一、代码二、效果三、解释 这段代码展示了一个基本的颜色表&#xff0c;方便参考使用&#xff0c;同时也应用了各种样式应用方式。 一、代码 <!DOCTYPE html> <html lang"zh-cn"> <head><title>编程笔记…

Redis开发规范与性能优化(二)

开发规范与性能优化 3.客户端使用 1.【推荐】避免多个应用使用一个Redis示例 正例:不相干的业务拆分&#xff0c;公共数据库做服务化 2.【推荐】使用带有连接池的数据库&#xff0c;可以有效控制链接&#xff0c;同时提高效率&#xff0c;标准使用方式如代码所示 public c…

AMD芯片使用Stable-Diffusion

AMD芯片使用Stable-Diffusion 由于A卡的Stable Diffusion工具的逐步完善&#xff0c;之前只能使用CPU跑&#xff0c;现在已支持AMD显卡进行AI绘图。 下载 官网链接&#xff1a;https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs 按…

LAMP网站部署(Discuz论坛网站部署)

目录 mysql命令 语法 选项 参数 实例 安装php 安装Mariadb 关掉防火墙和selinux 启动HTTP服务 初始化数据库 查看数据库是否创建成功 修改HTTP的配置文件 浏览器打开 将以下所有目录都加上权限 最后首页效果 mysql命令 是MySQL数据库服务器的客户端工具&#xff0c;它工作在命…

【Linux下qt软件安装打包附带问题: dpkg: error processing package xxxx +解决方式+自我尝试+记录】

【Linux下qt软件安装打包附带问题&#xff1a; dpkg: error processing package xxxx 解决方式自我尝试记录】 1、前言2、实验环境3、问题说明4、我的努力与查到解决的方式&#xff08;1&#xff09;补充两个文件&#xff0c;让软件正常执行&#xff08;2&#xff09;尝试修复d…

springboot+vue学生选课系统 java+ssm+idea+_mysql

系统包含三种角色&#xff1a;管理员、老师、学生&#xff0c;系统分为前台和后台两大模块&#xff0c;主要功能如下。 ide工具&#xff1a;IDEA 或者eclipse 编程语言: java 学生网上选课系统可以实现教室管理&#xff0c;老师管理&#xff0c;课程管理&#xff0c;教学计划管…

为什么我接不到大单?

以前的领导创业多年&#xff0c;今天找我聊了一下想让我跟他一起做点事情&#xff0c;聊了一下我的现状&#xff0c;突然让我明白为何我一直都接不到大单了 说起来也不是完全没有好的机会&#xff0c;貌似有点像“公交车定律”&#xff0c;当我很忙碌的时候订单一个接一个&…