Git是一个开源免费的分布式版本控制系统,可以快速高效的来管理项目代码。
[vplayer status="true"]
[Video url="https://www.bilibili.com/video/BV1Rb4y1C7z1" title="采用b站UP:Houor的视频" /]
[/vplayer]
yum -y install git
在本地主机会分三个区域,分别为工作区、暂存区、本地库,如果需要多人协作可以上传到一个远程仓库里面提供他人管理代码。
区域 | 作用 |
---|---|
工作区 | 写代码的过程都会在工作区内完成,写完之后需要上传到暂存区 |
暂存区 | 代码写完之后需要放到暂存区,确定没有问题之后需要把版本信息和暂存区的内容上传到本地库 |
本地库 | 全部的版本都在本地库里面 |
远程库 | 远程仓库是整个团队中所有人都可以访问的地方。 |
签名就是上传到本地库,远程仓库的时候的身份。
$ git config --global user.name "BoyChai"
$ git config --global user.email "1972567225@qq.com"
$ git config --global --list
默认本地是没有仓库的,这时候我们需要初始化一个仓库,进入到对应项目的目录执行命令"git init",例如
$ mkdir project
$ cd project/
$ git init
Initialized empty Git repository in /root/project/.git/
初始化好了之后会在本地创建一个".git"的目录,这个目录就是存放暂存区和本地库的地方。此时项目文件夹就是工作区。
此时目录里创建一个文件可以通过命令"git add [file]"将文件提交到暂存区,例如
$ echo 111 > test01
$ git add test01
提交完暂存区之后可以通过命令"git commit -m "[版本信息]""提交到本地库里面,例如
$ git commit -m "test01"
[master (root-commit) 776b640] test01
1 file changed, 1 insertion(+)
create mode 100644 test01
显示当前分支,并且查看在你上次提交之后是否有对文件进行再次修改。
git status
通过命令"git log"显示历史提交记录,例如
$ git log
commit 4240a74fc27134b79addead798a10d8d4808ec91
Author: BoyChai <1972567225@qq.com>
Date: Sat Jun 4 09:40:10 2022 -0400
test03
commit 93d1896fcc57d4b84733f70bffab8d68b56a2f0b
Author: BoyChai <1972567225@qq.com>
Date: Sat Jun 4 09:40:02 2022 -0400
test02
commit 776b640b6bf839f27a5ef099f33c11e66aa8f1da
Author: BoyChai <1972567225@qq.com>
Date: Sat Jun 4 09:38:43 2022 -0400
test01
也可以让他进行简易的输出提交记录
”git log --pretty=onelint“或“git log --oneline”
还可以使用命令“git reflog”来查看可引用的历史版本记录,他输出会带一个tag,输出内容如下
[root@gitlab project]# git reflog
4240a74 HEAD@{0}: commit: test03
93d1896 HEAD@{1}: commit: test02
776b640 HEAD@{2}: commit (initial): test01
可以让代码回到历史的某个版本
git reset --hard [版本ID]
版本的ID可以使用查看记录的方法获得
[root@gitlab project]# git reflog
4240a74 HEAD@{0}: commit: test03
93d1896 HEAD@{1}: commit: test02
776b640 HEAD@{2}: commit (initial): test01
[root@gitlab project]# git reset --hard 93d1896 //回滚到test02
HEAD is now at 93d1896 test02
如果涉及团队开发合作可以使用分支来分配工作,在写代码的时候,如果有多个功能需要去实现而且是一个团队进行编写,都在一个主分支上编写代码可能并不是很好管理,这个时候可以通过分支来管理,把每一个功能都单独创建一个分支让一个人去编写或者几个人去编写,当这个功能完善的时候就可以和主分支进行合并。
使用命令"git branch -v"来查看,例如
$ git branch -v
* master 93d1896 test02
使用命令"git branch [分支名称]"来创建,例如
$ git branch branch1
$ git branch -v
branch1 93d1896 test02
* master 93d1896 test02
使用命令"git checkout [分支名称]"来切换分支,例如
$ git checkout branch1
Switched to branch 'branch1'
$ git branch -v
* branch1 93d1896 test02
master 93d1896 test02
当分支的代码提交好了之后可以进行合并分支,合并分支需要将分支切换到master(主分支),然后使用命令"git merge [分支名称]"来合并分支,之后使用“commit”来提交,例如
$ git branch -v
* branch1 93d1896 test02
master 93d1896 test02
$ echo aaa > branch1_file01
$ git add branch1_file01
$ git commit -m "branch1_分支提交"
[branch1 af08213] branch1_分支提交
1 file changed, 1 insertion(+)
create mode 100644 branch1_file01
$ git checkout master
Switched to branch 'master'
$ git branch -v
branch1 af08213 branch1_分支提交
* master 93d1896 test02
[root@gitlab project]# echo bbb > master_file1
[root@gitlab project]# git add master_file1
[root@gitlab project]# git commit -m "master提交"
[master 731413b] master提交
1 file changed, 1 insertion(+)
create mode 100644 master_file1
[root@gitlab project]# git branch -v
branch1 af08213 branch1_分支提交
* master 731413b master提交
[root@gitlab project]# git merge branch1 //merge之后会弹出一下内容,第一行是写合并备注的,类似于命令"it commit -m"的备注
----------------------------------------------------------------------------------
Merge branch 'branch1'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
----------------------------------------------------------------------------------
//保存之后显示
Merge made by the 'recursive' strategy.
branch1_file01 | 1 +
1 file changed, 1 insertion(+)
create mode 100644 branch1_file01
$ git commit
# On branch master
nothing to commit, working directory clean
$ git branch -v
branch1 af08213 branch1_分支提交
* master 6a764f1 Merge branch 'branch1'
上面这个是主分支和分支都改变代码的情况下进行合并,如果没有改变主分支的代码就进行合并则不会弹出merge之后的内容
当分支和主分支的代码产生冲突该,例如
$ git branch branch2
$ git checkout master
Switched to branch 'master'
$ cat > file.txt <<EOF
> 111
> 222
> 444
> EOF
$ cat file.txt
111
222
444
$ git add file.txt
$ git commit -m "master_提交"
[master d7e9855] master_提交
1 file changed, 3 insertions(+)
create mode 100644 file.txt
[root@gitlab project]# git checkout branch2
Switched to branch 'branch2'
$ cat > file.txt <<EOF
> 111
> 222
> 333
> 444
> EOF
$ cat file.txt
111
222
333
444
$ git add file.txt
$ git commit -m "branch2_提交"
[branch2 3bac7d1] branch2_提交
1 file changed, 4 insertions(+)
create mode 100644 file.txt
此时master和分支branch2提交的最新版本的file.txt文件是有冲突的,这个时候进行合并会出现一下问题
$ git checkout master
Switched to branch 'master'
[root@gitlab project]# git branch -v
branch1 af08213 branch1_分支提交
branch2 3bac7d1 branch2_提交
* master d7e9855 master_提交
$ git merge branch2
Auto-merging file.txt
CONFLICT (add/add): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.
此时查看冲突文件会发现文件里的内容发生了改变
$ cat file.txt
111
222
<<<<<<< HEAD
=======
333
>>>>>>> branch2
444
文件的意思就是中间出现了333这一行,如果想要保留branch2分支的内容则就改成这样
$ cat file.txt
111
222
333
444
如果不想保留branch2分支的内容则就删除对应内容,例如
$ cat file.txt
111
222
444
上面两种保留方式选择一种之后,使用命令"git add [冲突文件]"来解决冲突,并使用命令"git commit"进行合并
$ cat file.txt
111
222
333
444
$ git add file.txt
$ git commit -m "master-branch2解决冲突"
[master 00721ab] master-branch2解决冲突
$ git branch -v
branch1 af08213 branch1_分支提交
branch2 3bac7d1 branch2_提交
* master 00721ab master-branch2解决冲突
远程仓库的类型有很多,Github,Gitee,Gitlab,Gogs等等,这里采用github作为示范,如图
推送代码到github之前还需要一个用户token,打开github的settings -> Developer settings -> Personal access tokens -> Generate new token,日期我选的7天权限根据自己情况自己勾选,之后店家Generate token,如图
之后当我们的代码已经提交完到本地库里了,我们可以通过命令"git push '仓库地址' '分支名称' "进行推送,推送过程中需要输入用户名和密码,这个密码实际上就是我们刚才创建的token,例如
$ git push https://github.com/BoyChai/Git_test.git master
Username for 'https://github.com': BoyChai
Password for 'https://BoyChai@github.com':
Counting objects: 20, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (20/20), 1.53 KiB | 0 bytes/s, done.
Total 20 (delta 7), reused 0 (delta 0)
remote: Resolving deltas: 100% (7/7), done.
To https://github.com/BoyChai/Git_test.git
* [new branch] master -> master
当远程仓库发生改变想要同步到本地的时候可以使用命令"git pull '仓库地址' '分支名称' ",例如
$ git pull https://github.com/BoyChai/Git_test.git master
From https://github.com/BoyChai/Git_test
* branch master -> FETCH_HEAD
Already up-to-date.
每次去推送、克隆代码的时候都需要输入一段很长的仓库地址,并不是很方便,可以使用命令"git remote add '别名' '仓库地址' "来创建别名,例如
$ git remote add git_test https://github.com/BoyChai/Git_test.git
$ git remote -v
git_test https://github.com/BoyChai/Git_test.git (fetch)
git_test https://github.com/BoyChai/Git_test.git (push)
之后相关代码仓库地址的位置都可以替换成别名来操作,例如
git push git_test master
git pull git_test master
团队协作需要在远程仓库里添加团队内部的人,在Github上的具体流程为 打开对应的项目 -> Settings -> Collaborators -> Add people
点击Select a collaborator above之后会给一个链接,需要发给对方进行验证,通过之后就可以在此仓库进行协作了
跨团队操作需要进行Fork操作,如图
点击fork之后会让你写一个仓库名称,之后这个仓库会以刚才的仓库名称变成你仓库里的一个项目,你可以自己任意更改提交克隆,当代码写好提交到自己fork的仓库之后,去对方的仓库里面点击pull requests
创建一个之后会出现一个版本比较的一个东西,让你选择版本进行对比,第一个选择就是他的仓库,第二个就是自己fork的仓库,选择好之后会出现修改的内容对比,然后进行创建,创建之后对方会受到一个请求,当对方同意的时候代码就会自动合并到对方仓库里。
]]>Netfilter/iptables(以下简称iptbales)是unix/linux自带的一款优秀切开放源代码的完全自由的基于包过滤的防护墙工具,他的功能十分强大,使用非常灵活,可以对流入和流出服务器的数据包进行很精细的控制。
Iptables是linux2.4以2.6内核中集成的服务。其功能与安全性比其老一辈ipfwadm,ipchains强大的多(长江后浪推前浪),iptable主要是工作在OSI模型的二三四层,如果重新编译内核,iptables也可以支持7层控制(squid代理+iptables)。
可以把Netfilter/iptables看作一栋楼,里面存放着很多的表。
表(tables)是链的容器,即所有的链(chains)都属于其对应的表(tables)上,可以把表(iptables)当作一套房子。
表有filter nat mangle raw四个表。
表名 | 作用 |
---|---|
filter表 | I负责过滤功能,内核模块:iptables_filter |
nat表 | 负责网络地址转换功能,内核模块:iptable_nat |
mangle表 | 解析报文,做出修改,重新封装的功能,内核模块:iptable_mangle |
raw表 | 关闭nat表上启用的链接追踪机制,内核模块:iptable_raw |
链(chains)是规则(Policys)的容器。如果把表(tables)当作一套房子,那么链就是里面的房间,卧室,厨房,客厅什么的。
链有INPUT OUTPUT FORWARD PREROUTING POSTROUTING 不同的表有不同的链
规(Policy)则就是一条条过滤的语句用来控制流量动作的。
表 | 链 |
---|---|
filter表 | INPUT,FORWARD,OUTPUT |
nat表 | PREROUTING,OUTPUT,POSTROUTING,INPUT(centos6没有) |
mangle表 | PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING |
raw表 | PREROUTING,OUTPUT |
主要是和自身有关,真正负责主机防火墙功能的(过滤流入流出主机的数据包)。Filter表是iptables默认使用的表,这个表定义了三个链(chains),工作场景主要是作为主机的防火墙。
INPUT链 负责过滤所有目标地址是本机地址的数据。通俗的讲,就是过滤进入主机的数据包。
FORWARD链 负责转发流经主机的数据包。起转发的作用,和nat关系很大,后面会详细介绍。 LVSNAT模式。net.ipv4.ip_forward = 0
OUTPUT链 处理所有源地址是本机地址的数据包。通俗的讲,就是处理从主机发去的数据包。
负责网络地址转换,即来源与目的ip地址和port的转换。主要应用于局域网共享上网或者特殊的端口转换服务相关。(和主机本身无关)
NAT功能一般用于的场景
OUTPUT链 和主机发出去的数据包有关。改变主机发出数据包的目标地址。
PREROUTING链 在数据包到达防火墙时进行路由判断之前执行的规则,作用是改变数据包的目的地址,目的端口等。(通俗的说就是收信时,根据规则重写收件人的地址)
POSTROUTING链 在数据包离开防火墙时进行路由判断之后的规则,作用改变数据包的源地址,源端口等。(通俗的说就是寄信的时候可以改变发件人的地址)
主要负责修改数据包中特殊的路由标记,如TTL,TOS,MARK等。这个表定义了5个链
INPUT FORWARD OUTPUT PREROUTING POSTROUTING
这个表基本用不到知道即可
主要是用来控制数据包是否需要通过iptables来处理的一个表 比如web服务器流量很大80端口默认开着需要filter表的INPUT是否来通过 使用RAW表之后则这条就不需要经过iptables防火墙了直接忽略通 防止流量过高 iptables处理不过来提高服务器性能
链只有两个
PREROUTING和OUTPUT
在表中数据包最早经过就是RAW所以可以让iptables不处理对应的数据包
iptables是采取包过滤机制工作的,所以它会对请求的数据包的包头数据进行分析、并根据我们预先设定的规则进行匹配来判断之后进行的动作。下图为过滤的流程图
下图为较为具体的工作流程图
下图为简易流程图
平常我们其实只需要顾及到nat的prerouting、postrouting和filter的input、forward以他的一般是用不到
systemctl start iptables //开启服务
systemctl stop iptables //关闭服务
systemctl enable iptables //设置开机自启
systemctl disable iptables //设置开机自动关闭
service iptables save //保存当前设置下次开机之后会生效
Ps:在centos7版本之后默认不会安装iptables-services,如果需要使用服务管理则需要安装一下"yum -y install iptables-services",iptables默认会有一个配置表(/var/sysconfig/iptabels这个文件) 这个表记录这本机的所有的iptables配置 每次开机之后都会找这个文件使其里面的配置生效service iptables save就是把当前临时的配置保存到这个表里使下次重载或者重启时生效 这一步很重要
iptables -L //列出表的规则 默认不加任何参数输出的时filter表的规则
iptables -F //清除所有的规则(无法清除默认的规则)
iptables -X //删除用户自定义的链(用的很少)
iptables -N //创建链(用的少)
iptables -Z //把链的计数器清零
iptables -t //指定表
iptables -t [表] -A //指定链以及添加规则的方式(在规则低端添加规则)
iptables -t [表] -I //指定链以及添加规则的方式(在规则顶端添加规则)
iptables -t [表] -D //指定链以及删除对应规则
iptables -t [表] -A/I [链] -p //指定ip协议tcp/udp
iptables -t [表] -A/I [链] –p [tcp/udp] --dport //指定目标端口
iptables -t [表] -A/I [链] -i //指定流入网卡
iptables -t [表] -A/I [链] -o //指定流出网卡
iptables -t [表] -A/I [链] -s //指定源地址
iptables -t [表] -A/I [链] [相应参数] -j //指定动作(一共三种通过(ACCEPT) 拒绝(REJECT) 丢弃(DROP))
因为NAT是负责网络转换这块,最好是把内核的转发更能打开,不然路由链就不生效
cat /etc/sysctl.conf |grep net.ipv4.ip_forward
net.ipv4.ip_forward = 1
sysctl -p //生效
Ip转换 一般用于局域网做网管内网ip转换为可上网的ip 提供内网主机上网使用
命令:
Iptables -t nat -A POSTROUTING -s 源地址 -d 0.0.0.0/0 -j SNAT –to-source 转换的ip
端口转发 一般用于端口转发做反向代理 可以防止内网主机完全暴露在公网环境中.
自己的端口转发
IP tables -t nat -A PREROUTING -p tcp –dport 本机端口 -J REDIRECT –to-port 转到端口
主机的端口转发
Iptables -t nat -A PREROUTING -p tcp –dport 本机端口 -J DNAT –to-destination 主机:端口
Ip伪装 一般用于局域网做网管内网ip转换为可上网的ip 提供内网主机上网使用
命令:
Iptables -t nat -A POSTROUTING -s 源地址 -d 0.0.0.0/0 -j MASQUERADE
systemctl是一个systemd中其中一个工具,主要用于控制systemd系统和各种服务的管理。在Linux生态系统中,Systemd被部署到了大多数的标准Linux发行版中,只有为数不多的几个发行版尚未部署。Systemd通常是所有其它守护进程的父进程,但并非总是如此。
目录 | 用处 | |
---|---|---|
/usr/lib/systemd/system/ | 每个服务最主要的启动脚本目录 | |
/run/systemd/system/ | 系统所生成的服务脚本目录,优先级比/usr/lib/systemd/system/高 | |
/etc/systemd/system/ | 自己创建的服务启动脚本目录,优先级/run/systemd/system/高 |
服务类型 | 全称 | 用处 |
---|---|---|
service | 一般服务类型 | 主要是系统服务,包括服务器本身所需要的本机服务以及网络服务,比较经常被使用到的服务大多是这种类型,所以,这也是最常见的类型。 |
socket | 内部程序数据交换的插槽服务 | 主要是IPC(Inter-processcommunication)的传输信息插槽(socketfile)功能。这种类型的服务通常在监控信息传递的插槽档,当有通过此插槽传递信息请求链接服务的时候,就依据当时的状态将该用户的请求传送到对应的daemon,若daemon尚未启动,则启动该daemon后再传送用户的请求。使用socket类型的服务一般是比较不会被用到的服务,因此在开机时通常会稍微延迟启动的时间。一般用于本机服务比较多,例如我们的图形界面很多的软件都是通过socket来进行本机程序数据交换的行为。 |
target | 执行环境类型 | 其实是一群unit的集合,例如multi-user.target其实就是一堆服务的集合。 |
mount | 文件系统挂载相关的服务 | 例如来自网络的自动挂载、NFS文件系统挂载等与文件系统相关性较高的程序管理。 |
path | 监测特定文件或目录类型 | 某些服务需要监测某些特定的目录来提供序列服务,例如最常见的打印服务,就是通过监测打印序列目录来启动打印功能。这时就得要.path的服务类型支持。 |
timer | 循环执行的服务 | 这个东西有点类似anacrontab,不过是由systemd主动提供的,比anacrontab更加有弹性 |
目录 | 使用 |
---|---|
启动服务 | systemclt start 服务名 |
关闭服务 | systemclt stop 服务名 |
重启服务 | systemclt restart 服务名 |
重载服务 | systemclt reload 服务名 |
开机自启动服务 | systemclt enable 服务名 |
开机自关闭服务 | systemclt disable 服务名 |
禁用服务 | systemclt mask 服务名 |
取消禁用 | systemctl unmask 服务名 |
服务状态 | systemctl status 服务名 |
[root@localhost ~]# systemctl status firewlald
Unit firewlald.service could not be found.
[root@localhost ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2022-05-22 11:01:43 EDT; 7min ago
Docs: man:firewalld(1)
Main PID: 932 (firewalld)
Tasks: 2 (limit: 11208)
Memory: 35.0M
CGroup: /system.slice/firewalld.service
└─932 /usr/libexec/platform-python -s /usr/sbin/firewalld --nofork --nopid
May 22 11:01:42 localhost.localdomain systemd[1]: Starting firewalld - dynamic firewall daemon...
May 22 11:01:43 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon.
May 22 11:01:43 localhost.localdomain firewalld[932]: WARNING: AllowZoneDrifting is enabled. This is considered an insecure configuration option. It >
已防火墙firewalld服务为例,Active:后面的就是服务当前的状态
状态 | 作用 |
---|---|
active(running) | 正有一个或多个程序正在被系统执行 |
active(exited) | 仅执行一次就正常结束的服务,目前并没有任何程序在系统中执行 |
active(waiting) | 正在执行当中,不过有需要等待其他的警告才能继续处理 |
inactive | 服务没有运行 |
dead | 程序已清除 |
在第二行的vendor preset:的后面有一个值这个值是指当前服务默认的启动方式
方式 | 作用 |
---|---|
enabled | 开机时自动运行 |
disabled | 开机时不运行 |
static | 被关联的服务,不可以被自己启动,但是可以通过某些服务进行唤醒启动 |
mask | 不允许被启动,被禁用了 |
自定义服务可以放到/etc/systemd/system/下,后缀名按照service来创建,列如test.service。
文件内容分为三个部分,如下下表
类 | 作用 |
---|---|
[Unit] | 定义服务的说明,信息 |
[UnitType] | 上面讲了服务类型,这里就是写服务类型的,不同的unit type就得要使用相对应的设置项目,本文只将service类型 |
[Install] | 关联target |
参数 | 作用 |
---|---|
Description | 用来写服务的简易说明的 |
Documentation | 一般用来写官方文档的地址 |
After | 声明某些服务,当那些服务开启之后自己才能启动,不是强制性的 |
Before | 声明某些服务,声明的服务开启时服务需要开启自己,也不是强制性的 |
Requires | 和After一样但是这个是强制性的 |
Wants | 和Before一样但是这个是强制性的 |
Conflicts | 声明服务,进行冲突检查,当声明的服务开启则自己不能启动 |
参数 | 作用 |
---|---|
Type | 启动的方式 |
EnvironmentFile | 开启服务时的环境配置变量 |
ExecStart | 开启服务的启动脚本 |
ExecStop | 关闭服务的停止脚本 |
ExecReload | 重置服务的重置脚本 |
Restart | 当Restart=1的时候,当服务自动关闭时它会自动再开启一个服务除非是用 systemctl强制停止服务 |
RemainAfterExit | 当RemainAfterExit=1的时候,服务停止时会自动启动 |
TimeoutSec | 要改变服务状态时无法正常更改则会按照TimeoutSec设置的时间之后进入"强制结束"状态 |
RestartSec | 和Restart差不多,这个可以设置时间,多久进行开启 |
方式 | 作用 |
---|---|
simple | 默认值,使用ExecStart来启动 |
forking | 理解为做为某个进程的子进程 |
oneshot | 与simple差不多,不过这个工作完后就结束了,不会常驻在内存中 |
dbus | 与 simple 差不多,但是必须要活得一个D-Bus的值才可以运行,用这个方式启动的时候还需要设置一个BusName=才行 |
idle | 要启动的时候必须要所有的工作都顺利执行完后才会执行,一般都是开机器最后运行的东西 |
参数 | 作用 |
---|---|
WantedBy | 一般都是已*.targetunit为后缀的文件,指定这个服务是在某个targetunit下,一般来说,大多的服务性质 unit 都是附挂在multi-user.target下面。 |
Also | 指出和服务一起安装或者被协助的单元。 |
Alias | 进行一个链接的别名的意思,当设置开机自启的时候则服务会进行链接文件的创建,命名由Alias来指定 |
Ansible 是一个极其简单的 IT 自动化平台,可让您的应用程序和系统更易于部署和维护。从代码部署到网络配置再到云管理,使用一种接近简单英语的语言,使用 SSH 实现一切自动化,无需在远程系统上安装代理。
GitHub:github.com/ansible/ansible
Ansible官网:www.ansible.com
配置好扩展源(epel-release)就可以使用yum安装了
yum -y install ansible
Ansible的配置文件存在优先级问题,默认状态下会使用/etc/ansible/ansible.cfg具体优先级关系如下:
最高优先级是执行命令的当前目录下
./ansible.cfg
如果当前目录下找不到配置文件就会查找执行用户的家目录寻找
~/.ansible.cfg
以上位置就会选择默认的配置文件
/etc/ansible/ansible.cfg
[root@host ~]# cp /etc/ansible/ansible.cfg ~/.ansible.cfg
[root@host ~]# vim ./anaconda-ks.cfg
//找到defaults段,这段不取消注释则采用默认配置,下面的参数可以自己配置
inventory /etc/ansible/hosts //主机清单文件路径
roles_path /etc/ansible/roles //role存放目录
remote_user root //执行命令的用户
//找到privilege_escalation段,这一块主要是和提权相关这里取不取消注释无所谓可以按照自己环境来修改
become=True //是否开启提权
become_method=sudo //定义执行方式
become_user=root //定义执行用户
become_ask_pass=False //定义提示密码
配置hosts主机文件
使用的时候需要定义host主机文件,里面是存放被控主机的ip地址,建议必须是使用可以ssh免密登录的主机。
[root@host ~]# echo "" > /etc/ansible/hosts //清除hosts主机文件
[root@host ~]# vim /etc/ansible/hosts //编辑hosts主机文件,并向里面添加主机
[host]
192.168.1.112
[host2]
192.168.1.113
hosts主机还有多种写法,具体请看本文的其他栏
ps:写好主机文件之后的操作需要建立在ssh免密之后才可以执行,具体方法可以看文章的其他栏,有问题欢迎在评论区提问
简单使用方法如下
[root@host ~]# ansible all --list //列出所有主机
hosts (2):
192.168.1.112
192.168.1.113
[root@host ~]# ansible all -m ping //验证全部主机的连通性
192.168.1.112 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.1.113 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[root@host ~]# ansible 组/主机 -m 模块 //使用-m参数来指定相应模块
ansible为每个模块都提供了文档
使用命令ansible-doc -l 可以列出全部的ansible模块
使用命令ansible-doc {模块名称} 可以查看对应模块的帮助文档
测试主机的连通性
直接使命令:ansible 主机/组 -m ping
[root@host ~]# ansible all -m ping
192.168.1.113 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.1.112 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
返回pong则证明连通性没问题
执行命令
直接使命令:ansible 主机/组 -m shell/command -a "执行的命令"
[root@host ~]# ansible all -m shell -a "ping baidu.com -c 1"
192.168.1.113 | CHANGED | rc=0 >>
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=50 time=18.5 ms
--- baidu.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 18.489/18.489/18.489/0.000 ms
192.168.1.112 | CHANGED | rc=0 >>
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=50 time=17.6 ms
--- baidu.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 17.597/17.597/17.597/0.000 ms
Shell和Command都是执行命令 但是两者有一定的区别
Command
该模块命令里如果有一下字符部分执行不成功 “<” “>” “|” “&””;”
Shell
用法基本和command一样 不过时通过/bin/sh进行执行,所以shell模块可以执行任何命令,就像在本机执行命令一样,但是这样有潜在的shell注入的风险
两个模块都要避免使用,你应该优先考虑ansible的模块
其他参数可以查看ansible-doc来详细学习
主要用于执行管理主机上的脚本 原理就是将shell复制到远程主机,再远程主机上执行
使用命令:ansible 主机/组 -m script -a "控制端的脚本"
[root@host ~]# echo "echo hello,world" > 1.sh
[root@host ~]# ansible all -m script -a './1.sh'
192.168.1.112 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.1.112 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.1.112 closed."
],
"stdout": "hello,world\r\n",
"stdout_lines": [
"hello,world"
]
}
192.168.1.113 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.1.113 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.1.113 closed."
],
"stdout": "hello,world\r\n",
"stdout_lines": [
"hello,world"
]
}
Stdout_lines参数就是实际机器返回的值
其他参数可以查看ansible-doc来详细学习
主要用于管理用户
使用命令:ansible 主机/组 -m user -a '参数'
添加一个用户ansible 主机/组 -m user -a ‘name=admin state=present’
state可以理解为动作 增加删除修改 默认state就是present
[root@host ~]# ansible all -m user -a "name=admin state=present"
192.168.0.103 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1000,
"home": "/home/admin",
"name": "admin",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1000
}
使用命令:ansible 主机/组 -m user -a ‘name=admin state=absent’ 可以删除admin用户
[root@host ~]# ansible all -m user -a "name=admin state=absent"
192.168.0.103 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"force": false,
"name": "admin",
"remove": false,
"state": "absent"
}
其他可以查看ansible-doc来详细学习
主要用于批量更新yum源
ansible 主机/组 -m yum_repository -a '参数'
ansible 主机/组 -m yum_repository -a 'name="CentOS" description="CentOS" baseurl="file:///mntcdrom" enabled=yes gpgcheck=no'
name 设置了文件名和文件中[]的内容
description 设置了文件中name的内容
baseurl 设置了文件中源的地址
enabled 设置了enable参数
gpgcheck 设置了是否需要密钥来验证包
[root@host ~]# ansible all -m yum_repository -a 'name="CentOS" description="CentOS" baseurl="file:///mntcdrom" enabled=yes gpgcheck=no'
192.168.0.103 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"repo": "CentOS",
"state": "present"
}
[root@host ~]# ssh root@192.168.0.103
Last login: Sun Apr 3 12:20:11 2022 from 192.168.0.102
[root@localhost ~]# cat /etc/yum.repos.d/CentOS.repo
[CentOS]
baseurl = file:///mntcdrom
enabled = 1
gpgcheck = 0
name = CentOS
他会在对控制主机里生成相应的yum源配置文件
还有很多参数可以用ansible-doc yum_repository来查看文档
主要是用来操作yum的
ansible 主机/组 -m yum -a ‘参数’
参数详解
Name 包名
State 选择是安装还是删除还是更新(present和installed是安装 latest是更新 removed和absent是移除)
这是基本使用 还有很多参数详情请使用ansible-doc yum查看
主要是用来批量传输文件的
ansible 主机/组 -m copy -a ‘参数’
src 写本地目录
dest 客户端目录
其他请使用ansible-doc copy查看
主要是用来管理服务用的
ansible 主机/组 -m service -a ‘参数’
name 包名
state 设置状态(started开启 stopped关闭 restarted重启 reloaded重置)
enabled 参数只有yes和no yes为开机自启 no就是开机不开启
其他请使用ansible-doc service查看
主要是用来显示对应主机的facts变量的,写roles文件用的比较多
ansible 主机/组 -m setup -a ‘参数’
用来显示对应主机的facts变量
使用参数 filter=’关键词 可以进行显示检索
具体请使用ansible-doc setup来查看’
用来管理firewalld防护墙
ansible 主机/组 -m firewalld -a ‘参数’
参数:
Service 设置服务名称
Permanent 是否永久更改(yes,no)
State 是否放行(enabled,disabled)
Zone 选择区域
Port 设置端口(/tcp,/udp)
其他具体请使用ansible-doc firewalld来查看
主要是用来复制jnja2文件的,jnja2文件后面会讲
ansible 主机/组 –m template -a ‘参数’
src 文件目录
dest 复制后的文件目录
其他参数请使用ansible-doc template查看
主要是用来debug的输出信息
ansible 主机/组 -m debug -a ‘参数’
msg 输出内容
var 输出变量
其他请使用ansible-doc debug查看
Playbook剧本 类似和脚本一样 用来批量执行模块
Playbook有着严格的缩进写法,语法非常严谨,使用yml文件来写
[root@host test]# cat creatuser.yml
---
- name: create user
hosts: 192.168.0.103
tasks:
- name: create admin
user:
name: admin
state: present
开头必须使用---
一个-代表一个任务的开头
如果一个块需要配置子参数则就需要严格缩进
name是描述
Hosts是主机清单
Tasks是配置任务
子任务中name是描述
User则就代表user模块
模块的子参数就不需要-了
name则是user的配置参数
运行playbook的命令是ansible-playbook palybook文件
这是执行除此之外还可以使用命令"ansible-playbook --syntax-check 文件"来检查文件语法是否有误
还有命令"ansible-playbook -C 文件"来运行测试,他会使用文件进行运行测试但不会在目的主机上发生实际改变
变量的名称必须以字母开头,并且只能含有字母,数字和下划线.
通过vars声明变量通过“{{变量名}}”进行调用
左边的就是使用变量写的,右边就是没用.实质效果一样
也可以通过指定一个变量文件来实现 参数:vars_files:文件名
我这边定义的是相对目录下的vars.yml 然后图的右边就是vars.yml文件的内容
魔法变量是ansible的内置变量,直接被定义好的,可以直接拿来使用.
常见的魔法变量:
hostvars 列出所有受管理的主机信息.啊如果没有收集facts信息则不会显示facts信息
group_names 列出当前受管理主机所属的所有组
groups 列出清单中所有组的字典/映射
inventory_hostname 列出清单中所有配置的当前主机名称
其他的可以使用setup模块进行查看
Facts变量用于采集客户端的信息,比如网络信息,主机名,硬件信息等.
每次执行playbook时会对客户端主机进行数据采集
实际上它是通过setup模块进行收集数据
Ansible 主机/组 -m setup可以列出所有的facts变量
When就是判断 他只会判断某一条是否为true 否则跳过 可以理解为判断一个布尔类型
When虽然不是一个模块但是他的缩进必须和模块对其 卸载tasks后面
---
- name: create user
hosts: 192.168.0.104
vars:
run: true
tasks:
- name: create user
user:
name: admin
state: present
when: run
这是单条的判断 when会判断上面的值是否为true 是则执行不是则跳过
---
- name: create user
hosts: 192.168.0.104
tasks:
- name: create user
user:
name: admin
state: presend
when:
- ansible_distribution == "CentOS" and ansible_machine == "x86_64"
- ansible_distribution == "CentOS" and ansible_machine == "RedHat"
里面的两个值都是facts的变量,只有满足CentOS系统内核为x86和redhat的系统才会执行,否则跳过
只有满足CentOS系统内核为x86和redhat的系统才会执行 否则跳过
常用判断语句
== 等于
< 小于
> 大于
<= 小于等于
>= 大于等于
!= 不等于
is defined 变量是否定义,定义为true 未定义为false
si not defined 变量是否定义,未定义为false
魔法变量判断
when: inventory_hostname in groups[“VMhost”]
只有VMhost组中主机才会执行此操作
---
- name: create user
hosts: 192.168.0.104
tasks:
- name: create user
user:
name: "{{item.name}}"
uid: "{{item.uid}}"
state: presend
loop:
- name: admin1
uid: 3001
- name: admin2
uid: 3002
- name: admin3
uid: 3003
Item是循环变量 只要用loop循环执行变量就必须使用item 点的后面使用loop定义的内容 循环的开始都要用 – 表示
Ansble的playbook可以把多个和任务组成一个块,然后根据不同条件来执行这个块
还能执行失败时执行其他命令
Block 定义块 写的时候要求和任务(tasks)的name对齐
Rescue 当上面的块执行失败时,该关键字下麦呢的任务将被执行
Always 不管block是否执行成功之后都会执行这个任务
---
- name: cat file
hosts: 192.168.0.104
tasks:
- name: cat a.txt
block:
- debug:
msg: "查看文件"
- shell: cat /1.txt
rescue:
- debug:
msg: "我giao,查看失败,创建文件"
- shell: echo hello,world > /1.txt
- debug:
msg: "查看文件"
- shell: cat /1.txt
always:
- debug:
msg: "执行完成"
如下执行结果
以上一个block为例子,给他改一些东西
---
- name: cat file
hosts: 192.168.0.104
tasks:
- name: cat a.txt
block:
- debug:
msg: "查看文件"
- shell: cat /1.txt
- debug:
var: cattxt
register: cattxt
rescue:
- debug:
msg: "我giao,查看失败,创建文件"
- shell: echo hello,world > /1.txt
- debug:
msg: "查看文件"
- shell: cat /1.txt
always:
- debug:
msg: "执行完成"
执行结果如下
Ansible roles提供了便捷的方式让你能够轻松的重复利用ansible代码 可以在标准化的目录结构中大伯所有 任务 变量 文件 模板以及完成任务所需要的资源,这样我们只需要将roles从一个项目复制到另一个项目即可在play中直接调用并执行他
从第二排开始就是roles的文件 文件中包含很多项目就是第三排的内容 然后第四行就是每个项目中的子目录 这几个子目录都有自己的作用
Default: 此目录中main.yml文件定义新角色变量的默认值,该目录中定义的优先级较低,使用角色时可以覆盖这些变量
Files: 存放角色任务中引用的静态文件
Handlers: 此目录中main.yml 文件定义处理程序
Meta: 此目录中main.yml 文件定义角色相关信息 如:作者,平台,依赖等等
Tasks: 此目录中main.yml 文件定义角色中的任务
Templates: 存放jinja2的模板文件
Tests: 此目录中可以包含清单和test.yml(playbook)用于测试角色
Vars: 此目录中main.yml文件定义角色使用的变量值,优先级高于default目录
Galax是ansible的一个功能库 你可以使用其他人创建好的roles也可以分享自己的roles.
就像docker镜像库一样 需要什么功能就可以直接去下载使用
官方网站:https://galaxy.ansible.com
Ansible-galaxy install 包名
默认安装会的话会自动安装到~/.ansible/roles/下 可以使用-p参数指定位置
然后参数init可以自动生成roles目录
Ansible-galaxy init 文件夹名字
参数 -r 可以执行yml下载文件
例如
---
- src: roles文件地
name: 下载后的本地昵称
- src: roles文件地址
name: 下载后的本地昵称
安装的时候可以使用命令
Ansible-galaxy install -r yml.yml 进行下载
装好的角色可以使用ansible-galaxy list查看
J2全名为jinja2是python下一个被广泛运用的模板引擎,他的设计思想来源于Django的模板引擎,并拓展了其他语法和一系列强大的功能,ansible使用jinja2模板来启用动态表达式和访问变量。
Jinja2模板的构成:数据 变量 表达式
在使用jinja2模板时变量和表达式会被替代成对应的值,变量的值可以在plasybook中定义也可以直接调用facts事实,当然调用facts需要你编写的playbook开启了facts收集
{{EXPR}} 用于装载表达式,比如变量,运算表达式,比较表达式
{%EXPR%} 用于装载控制语句 比如if,for等
{# #} 用于注释
Ps:jinja2模板文件本身不需要指定文件扩展名,使用.j2为后缀名只是为了更方便我们管理jinja2的模板
使用命令"ansible-galaxy init galaxy"创建一个galaxy模板
[root@Ansible roles]# ansible-galaxy init galaxy
- Role galaxy was created successfully
[root@Ansible roles]# ls
galaxy
[root@Ansible roles]# cd galaxy/
[root@Ansible galaxy]# ls
defaults files handlers meta README.md tasks templates tests vars
编辑tasks的main.yml文件写入以下内容
---
# tasks file for galaxy
- name: install apache
yum:
name: httpd
- name: start httpd
service:
name: "{{item}}"
state: started
enabled: yes
loop:
- httpd
- firewalld
- name: set firewalld
firewalld:
service: http
permanent: yes
state: enabled
immediate: yes
- name: set index
template:
src: index.html.j2
dest: /var/www/html/index.html
tasks/main.yml文件只需要定义命令,不需要定义主机
上面这个main文件是使用yum下载了一个httpd之后使用service开启了防火墙和httpd的服务,又实用防火墙模块放行了对应的服务,之后把j2文件复制到了对应的网站目录页面。
之后写一个j2文件放到templates目录里,内容如下
[root@Ansible galaxy]# cat templates/index.html.j2
Welcome to {{ansible_default_ipv4.address}}
ansible_default_ipv4.address是facts变量中对应主机的ip
写好之后我们来写一个playbook来运行写的roles
---
- name: roles galaxy
hosts: 192.168.0.104
roles:
- /root/ansible/roles/galaxy
运行结果如下,通过http访问返回内容
使用ansible的时候难免会有一些比较敏感的数据,比如密码,key等信息直接明文暴露显然不是很好,vault管理加密/解密yml(palybook)文件工具,有时编写的playbook文件中会存在重要敏感信息,考虑到安全,可以使用此工具进行加密!
Ansible-vault [参数] [文件]
Create: 创建
Decrypt: 解密
Edit: 编辑加密文件
Encrypt: 加密
rekey: 修改口令
view: 查看
加密之后执行playbook的时候需要附加–ask-vault-pass参数
创建用户,用户信息使用vault进行加密,使其不能以明文的形式查看
[root@Ansible ansible]# cat vault.yml
---
- name: vault
vars_file: ./userinfo.yml
tasks:
- name: create user
user:
name: "{{name}}"
password: "{{password}}"
[root@Ansible ansible]# cat userinfo.yml
---
- name: "admin"
password: "abc123"
[root@Ansible ansible]# ansible-vault encrypt userinfo.yml
New Vault password:
Confirm New Vault password:
Encryption successful
[root@Ansible ansible]# cat userinfo.yml
$ANSIBLE_VAULT;1.1;AES256
63356239383039396263323732396663333132616561323362636662383265626233643465376365
3838633930316666373234633533643065643238653239380a313530633763366262643135363336
62386533313439393761353966316534323464326533306564363565623737393766316231383035
6361363665333837320a316465306139373564623930303330623261343466366336653537333266
61386330336363366633633632303465613535303766653663363734663138393064646237363063
3431616565353131633931326531383262353234366131306130
执行需要使用参数 "–ask-vault-pass" 执行
一般写法:
[组名]
IP
域名
······
连续主机写法:
[组名]
1[a-f].example.com
······
父组写法:
[组名:children]
组名
组名
······