Ansible common modules

Posted by jonki on Sun, 16 Jan 2022 11:08:28 +0100

1Ansible common module details

1.1 module introduction

  • Modules are tools for temporary commands to complete tasks. Ansible provides hundreds of modules that can complete different tasks. Usually, we can find a tested special module to complete the required tasks as part of the standard installation
  • The ansible doc - L command can list all modules installed on the system. You can use ansible doc to view the help document of a specific module by name, and then find information about what parameters the module will take as options
  • Most modules take parameters. A list of parameters available for the module can be found in the module's documentation. You can pass parameters to the module with the - a option. When no parameters are required, the - a option can be omitted from the. If you need to specify more than one parameter, provide it as a space delimited list enclosed in quotation marks

1.2 module classification

Module typemodular
File moduleCopy: copy the local file to the managed host file: set the permissions and other properties of the file lineinfile: ensure that a specific line is synchronized in the file synchronize: synchronize content using rsync
Software package modulePackage: manage packages using the automatic detection package manager native to the operating system yum: manage packages using yum APT: manage packages using APT dnf: manage packages using dnf gem: manage Ruby gempip: manage Python packages from PyPI
System moduleFirewalld: use firewalld to manage firewall reboot: restart the computer service: manage service user: add, delete and manage user accounts
Net Tools moduleget_url: download files via HTTP, HTTPS or FTP nmcli: manage network uri: interact with Web Services

Other modules

  • Cloud module
  • Command module
  • Database module
  • Asset module
  • Message module
  • Monitoring module
  • Network module
  • Notification module
  • Source control module
  • Unit module
  • web Facility module
  • windows module

1.3 ansible common modules

  • ping
  • yum
  • template
  • copy
  • user
  • group
  • service
  • raw
  • command
  • shell
  • script

1.4 differences between common modules raw, command and shell of ansible

command, shell module:

  • python is required to be installed on the managed host. command can execute shell commands on the managed host, but environment variables and operators are not supported (such as' | '.' < ',' > ',' & ')
  • The / bin/sh instruction called by the shell module executes

raw module:

  • Instead of installing python on the managed host, run the command directly using the remote shell
  • Typically used on systems where python cannot be installed (such as network devices)

2Ansible common modules

2.1 Ping module

The ping module is used to check whether the specified node machine is connected. The usage is very simple and does not involve parameters. If the host is online, it will reply to pong

[root@localhost ansible]# ansible all -m ping
192.168.25.130 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

2.2command module

The command module is used to execute commands on the remote host. ansible uses the command module by default. (that is, the command module is used by default without specifying the module)

[root@localhost ansible]# ansible all -m command -a 'ls /opt'
192.168.25.130 | CHANGED | rc=0 >>
abc

[root@localhost ansible]# ansible all -a 'ls /opt'
192.168.25.130 | CHANGED | rc=0 >>
abc

command module parameters

  • Chdir specifies a directory. Before executing the command, you will enter the directory specified by chdir
[root@localhost ansible]# ansible all -m command -a "chdir=/opt/ ls"
192.168.25.130 | CHANGED | rc=0 >>
abc

  • creates creates does not help us create files. Its purpose is that when the specified file exists, the command will not be executed. For example, when the / opt/abc file exists, the specified command will not be executed
[root@node1 ~]# cd /opt/
[root@node1 opt]# ls
abc
[root@localhost ansible]# ansible all -m command -a "creates=/opt/abc echo redhat-test"
192.168.25.130 | SUCCESS | rc=0 >>
skipped, since /opt/abc exists


  • When / opt/abc does not exist, execute the RedHat test command
[root@node1 ~]# cd /opt/
[root@node1 opt]# ls
[root@node1 opt]# 

[root@localhost ansible]# ansible all -m command -a "creates=/opt/abc echo redhat-test"
192.168.25.130 | CHANGED | rc=0 >>
redhat-test

  • Remove when the specified file does not exist, the command will not be executed
[root@node1 ~]# cd /opt/
[root@node1 opt]# ls
[root@node1 opt]# 
[root@localhost ansible]# ansible all -m command -a "removes=/opt/abc echo redhat-test"
192.168.25.130 | SUCCESS | rc=0 >>
skipped, since /opt/abc does not exist
  • When / opt/abc exists, execute the redha test command
[root@node1 ~]# cd /opt/
[root@node1 opt]# ls
abc
[root@localhost ansible]# ansible all -m command -a "removes=/opt/abc echo redhat-test"
192.168.25.130 | CHANGED | rc=0 >>
redhat-test

  • touch create file
[root@localhost ansible]# ansible all -m command -a 'touch /opt/ll'
[WARNING]: Consider using the file module with state=touch rather than running
'touch'.  If you need to use command because file is insufficient you can add 'warn:
false' to this command task or set 'command_warnings=False' in ansible.cfg to get
rid of this message.
192.168.25.130 | CHANGED | rc=0 >>

[root@localhost ansible]# ansible all -m command -a 'chdir=/opt/ ls'
192.168.25.130 | CHANGED | rc=0 >>
abc
ll

One drawback of the command module is that it cannot use pipeline characters and redirection functions

[root@localhost ansible]# ansible all -m command -a "echo 'hello world' > /opt/ll"
192.168.25.130 | CHANGED | rc=0 >>
hello world > /opt/ll
[root@localhost ansible]# ansible all -m command -a 'cat /opt/ll'
192.168.25.130 | CHANGED | rc=0 >>
[root@localhost ansible]# ansible all -m command -a 'ps -ef|grep vsftpd'
192.168.25.130 | FAILED | rc=1 >>
error: unsupported SysV option

Usage:
 ps [options]

 Try 'ps --help <simple|list|output|threads|misc|all>'
  or 'ps --help <s|l|o|t|m|a>'
 for additional help text.

For more details see ps(1).non-zero return code

2.3raw module

The raw module is used to execute commands on a remote host and supports pipeline characters and redirection

//Support redirection
[root@localhost ansible]# ansible all -m raw -a 'echo "hell word" > /opt/ll'
192.168.25.130 | CHANGED | rc=0 >>
Shared connection to 192.168.25.130 closed.

[root@localhost ansible]# ansible all -m raw -a 'cat /opt/ll'
192.168.25.130 | CHANGED | rc=0 >>
hell word
Shared connection to 192.168.25.130 closed.


//Supports pipe characters
[root@localhost ansible]# ansible all -m raw -a 'ss -antl'
192.168.25.130 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    
LISTEN    0         128                0.0.0.0:111              0.0.0.0:*       
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*       
LISTEN    0         5                127.0.0.1:631              0.0.0.0:*       
LISTEN    0         128              127.0.0.1:6010             0.0.0.0:*       
LISTEN    0         128              127.0.0.1:6011             0.0.0.0:*       
LISTEN    0         128                   [::]:111                 [::]:*       
LISTEN    0         128                   [::]:22                  [::]:*       
LISTEN    0         5                    [::1]:631                 [::]:*       
LISTEN    0         128                  [::1]:6010                [::]:*       
LISTEN    0         128                  [::1]:6011                [::]:*       
Shared connection to 192.168.25.130 closed.

[root@localhost ansible]# ansible all -m raw -a 'ss -antl|grep 22'
192.168.25.130 | CHANGED | rc=0 >>
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*       
LISTEN    0         128                   [::]:22                  [::]:*       
Shared connection to 192.168.25.130 closed.

2.4 shell module

  • The shell module is used to execute scripts on the controlled machine, or directly execute commands on the controlled machine, and the shell module also supports pipeline and redirection
  • When the shell module executes commands in the remote host, it will be processed by the / bin/sh program on the remote host
//Script file
[root@node1 ~]# vim test.sh
[root@node1 ~]# cat test.sh 
#!/bin/bash

echo "hello word"
[root@node1 ~]# chmod +x test.sh 
[root@node1 ~]# ll
 Total consumption 12
drwxr-xr-x. 2 root root    6 11 February 2020 public
drwxr-xr-x. 2 root root    6 11 February 2020 template
drwxr-xr-x. 2 root root    6 11 February 2020 video
drwxr-xr-x. 2 root root    6 11 February 2020 picture
drwxr-xr-x. 2 root root    6 11 February 2020 document
drwxr-xr-x. 2 root root    6 11 February 2020 Download
drwxr-xr-x. 2 root root    6 11 February 2020 music
drwxr-xr-x. 2 root root    6 11 February 2020 desktop
-rw-------. 1 root root 1230 11 February 2020 anaconda-ks.cfg
-rw-r--r--. 1 root root 1385 11 February 2020 initial-setup-ks.cfg
-rwxr-xr-x. 1 root root   31 7 March 17:49 test.sh

//Viewing script files for controlled hosts
[root@localhost ansible]# ansible all -m command -a 'cat test.sh'
192.168.25.130 | CHANGED | rc=0 >>
#!/bin/bash

echo "hello word"

//Use the shell module to execute the script on the controlled machine on the controlled machine
[root@localhost ansible]# ansible all -m shell -a '/bin/bash /root/test.sh &> /opt/test.log'
192.168.25.130 | CHANGED | rc=0 >>
[root@localhost ansible]# ansible all -m command -a 'cat /opt/test.log'
192.168.25.130 | CHANGED | rc=0 >>
hello word

2.5 script module

The script module executes the script on the ansible management host on the controlled host. The script exists on the ansible management host and does not need to be copied to the controlled host before execution (that is, the script module is used to execute the script on the master on the controlled host)

//Script file
[root@localhost ansible]# ls
ansible.cfg  hosts  inventory  roles
[root@localhost ansible]# mkdir scripts
[root@localhost ansible]# cd scripts/
[root@localhost scripts]# vim test.sh
[root@localhost scripts]# cat test.sh
#!/bin/bash

useradd tom
echo "redhat" | passwd --stdin tom
echo "hello word" > ~tom/abc

//Execute the script file on the host computer
[root@localhost ansible]# ansible all -m script -a 'scripts/test.sh'
192.168.25.130 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 192.168.25.130 closed.\r\n",
    "stderr_lines": [
        "Shared connection to 192.168.25.130 closed."
    ],
    "stdout": "Change user tom Your password.\r\npasswd: All authentication tokens have been successfully updated.\r\n",
    "stdout_lines": [
        "Change user tom Your password.",
        "passwd: All authentication tokens have been successfully updated."
    ]
}

//View the content on the controlled machine
[root@node1 ~]# id tom
uid=1001(tom) gid=1002(tom) group=1002(tom)
[root@node1 ~]# cd /home/tom/
[root@node1 tom]# ls
abc
[root@node1 tom]# cat abc 
hello word

2.6 template module

  • The template module can transfer the configuration file with parameters to the target address, and modify and backup the parameters of the file
  • The template module is used to generate a template and transfer it to a remote host
//transfer files
[root@localhost ansible]# ansible all -m template -a 'src=~/anaconda-ks.cfg dest=/opt/hehe'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "checksum": "4e0b9a45ca5724c0e46a70d56213e1d90f2f0595",
    "dest": "/opt/hehe/anaconda-ks.cfg",
    "gid": 0,
    "group": "root",
    "md5sum": "a840aed2908e3fca668c10f7face84cc",
    "mode": "0644",
    "owner": "root",
    "secontext": "system_u:object_r:usr_t:s0",
    "size": 1230,
    "src": "/root/.ansible/tmp/ansible-tmp-1626510875.6001868-10108-259486274186289/source",
    "state": "file",
    "uid": 0
}
[root@node1 ~]# head -3 /opt/hehe 
#version=RHEL8
ignoredisk --only-use=nvme0n1
autopart --type=lvm

2.7yum module

  • The yum module helps us manage the package through Yum source on the managed host

main parameter
name specifies the package to be managed
State specifies the state of the package

statec common values
present ensure that the software package is installed [installed]
Latest means install the latest version from yum
removed means to delete the corresponding software package [absent]

//Query whether vsftpd software is installed on the controlled machine
[root@node1 ~]# rpm -qa|grep vsftpd
[root@node1 ~]# 

//On the management host, install vsftpd on the controlled machine through the yum module
[root@localhost ansible]# ansible all -m yum -a 'name=vsftpd state=present'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: vsftpd-3.0.3-31.el8.x86_64"
    ]
}

//Query whether the controlled machine is installed with vsftpd on the management host
[root@localhost ansible]# ansible all -m shell -a 'rpm -qa | grep vsftpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
If you need to use command because yum, dnf or zypper is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to
get rid of this message.
192.168.25.130 | CHANGED | rc=0 >>
vsftpd-3.0.3-31.el8.x86_64

//Uninstall vsftpd on the controlled machine through yum module on the management host
[root@localhost ansible]# ansible all -m yum -a 'name=vsftpd state=absent'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Removed: vsftpd-3.0.3-31.el8.x86_64"
    ]
}

//Query whether vsftpd on the controlled machine is uninstalled on the management host
[root@localhost ansible]# ansible all -m shell -a 'rpm -qa | grep vsftpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
If you need to use command because yum, dnf or zypper is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to
get rid of this message.
192.168.25.130 | FAILED | rc=1 >>
non-zero return code

2.8 copy module

The copy module copies files from the ansible management host to the managed host

Common parameters

  • src [source] specifies the file or directory to copy
  • dest [destination] specifies the directory where the file will be copied to the controlled host
  • Content when you do not use src to specify the copied file, you can use content to specify the file content directly
//Copy the inventory on the management host to the control host
[root@localhost ansible]# ansible all -m copy -a 'src=/etc/ansible/inventory dest=/opt/inventory'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "checksum": "895cbc69037e6266a4cc5ac0b702ecbc6e5f93c9",
    "dest": "/opt/inventory",
    "gid": 0,
    "group": "root",
    "md5sum": "fb1a9c0d2acdde2788955941206a48f8",
    "mode": "0644",
    "owner": "root",
    "secontext": "system_u:object_r:usr_t:s0",
    "size": 67,
    "src": "/root/.ansible/tmp/ansible-tmp-1626513540.3747706-10780-226187928193702/source",
    "state": "file",
    "uid": 0
}
[root@node1 ~]# cd /opt/
[root@node1 opt]# ls
abc  hehe  inventory  ll  test.log
[root@node1 opt]# cat inventory 

[webservers]
192.168.25.130  ansible_user=root ansible_password=1

2.9 group module

The group module helps us manage groups on controlled hosts

Common parameters
Name specifies the name of the group to operate on
sate specifies the status of the Group [present creates a group, absent deletes a group]
gid specifies the gid of the group
Change system to system group (yes/no)

//Add a system group on the controlled machine with gid 306 and group name mysql
[root@localhost ansible]# ansible all -m group -a 'name=mysql gid=306 state=present'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "gid": 306,
    "name": "mysql",
    "state": "present",
    "system": false
}

//See if a group is created on the controlled host
[root@localhost ansible]# ansible all -m shell -a 'grep mysql /etc/group'
192.168.25.130 | CHANGED | rc=0 >>
mysql:x:306:

//Change mysql group to system group
[root@localhost ansible]# ansible all -m group -a 'name=mysql gid=306 system=yes'
192.168.25.130 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "gid": 306,
    "name": "mysql",
    "state": "present",
    "system": true
}

//Change the gid of mysql group
[root@localhost ansible]# ansible all -m group -a 'name=mysql gid=600 '
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "gid": 600,
    "name": "mysql",
    "state": "present",
    "system": false
}
[root@localhost ansible]# ansible all -m shell -a 'grep mysql /etc/group'
192.168.25.130 | CHANGED | rc=0 >>
mysql:x:600:

//Delete mysql group
[root@localhost ansible]# ansible all -m group -a 'name=mysql state=absent '
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "name": "mysql",
    "state": "absent"
}
[root@localhost ansible]# ansible all -m shell -a 'grep mysql /etc/group'
192.168.25.130 | FAILED | rc=1 >>
non-zero return code

2.10user module

The user module is used to manage users on the controlled host, such as creating users, deleting users, modifying users, deleting users, creating keys for users, etc

Common parameters
Name specifies the name of the user
Group specifies the base group of the user
groups specifies the additional group that the user is in
Shell specifies the default shell for the user
Uid specifies the uid of the user
create_home creates a home for a user when the user is created or when the home directory does not exist
System specifies whether the user is a system user

//Add a system user on the controlled machine, whose user name is mysql, uid is 306, and its shell is set to / sbin/nologin. There is no home directory
[root@localhost ansible]# ansible all -m user -a 'name=mysql uid=306 shell=/sbin/nologin system=yes create_home=no'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "comment": "",
    "create_home": false,
    "group": 306,
    "home": "/home/mysql",
    "name": "mysql",
    "shell": "/sbin/nologin",
    "state": "present",
    "system": true,
    "uid": 306
}
[root@localhost ansible]# ansible all -m shell -a 'grep mysql /etc/passwd'
192.168.25.130 | CHANGED | rc=0 >>
mysql:x:306:306::/home/mysql:/sbin/nologin
[root@localhost ansible]# ansible all -m shell -a 'ls /home'
192.168.25.130 | CHANGED | rc=0 >>
ii
runtime
tom

//Modify user's uid
[root@localhost ansible]# ansible all -m user -a 'name=mysql uid=360'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "append": false,
    "changed": true,
    "comment": "",
    "group": 306,
    "home": "/home/mysql",
    "move_home": false,
    "name": "mysql",
    "shell": "/sbin/nologin",
    "state": "present",
    "uid": 360
}
[root@localhost ansible]# ansible all -m shell -a 'grep mysql /etc/passwd'
192.168.25.130 | CHANGED | rc=0 >>
mysql:x:360:306::/home/mysql:/sbin/nologin

//Delete the mysql user on the controlled host
[root@localhost ansible]# ansible all -m user -a 'name=mysql state=absent'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "force": false,
    "name": "mysql",
    "remove": false,
    "state": "absent"
}
[root@localhost ansible]# ansible all -m shell -a 'grep mysql /etc/passwd'
192.168.25.130 | FAILED | rc=1 >>
non-zero return code

2.11 service module

The service module helps us manage the services on the controlled host

Common parameters
Name specifies the name of the service to be operated
state specifies the status of the service [started, stopped]
enabled specifies whether the service is set to start automatically (yes/no)

//Check whether vsftpd service is installed on the controlled machine
[root@localhost ansible]# ansible all -m shell -a 'rpm -qa |grep vsftpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.  If
you need to use command because yum, dnf or zypper is insufficient you can add 'warn:
false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of
this message.
192.168.25.130 | FAILED | rc=1 >>
non-zero return code

//Install the vsftpd service on the controlled host
[root@localhost ansible]# ansible all -m yum -a 'name=vsftpd state=present'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: vsftpd-3.0.3-31.el8.x86_64"
    ]
}
[root@localhost ansible]# ansible all -m shell -a 'rpm -qa |grep vsftpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.  If
you need to use command because yum, dnf or zypper is insufficient you can add 'warn:
false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of
this message.
192.168.25.130 | CHANGED | rc=0 >>
vsftpd-3.0.3-31.el8.x86_64

//Check whether the vsftpd service on the controlled machine is started
[root@localhost ansible]# ansible all  -m shell -a 'systemctl is-active vsftpd'
192.168.25.130 | FAILED | rc=3 >>
inactivenon-zero return code

//Start the vsftpd service on the controlled machine
[root@localhost ansible]# ansible all -m service -a 'name=vsftpd state=started'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "name": "vsftpd",
    "state": "started",
    "status": {
        "ActiveEnterTimestampMonotonic": "0",
        "ActiveExitTimestampMonotonic": "0",
        "ActiveState": "inactive",
        "After": "systemd-journald.socket basic.target system.slice sysinit.target network.target",
        "AllowIsolate": "no",
        "AllowedCPUs": "",
......

//Check whether the vsftpd service on the controlled machine is started
[root@localhost ansible]# ansible all  -m shell -a 'systemctl is-active vsftpd'
192.168.25.130 | CHANGED | rc=0 >>
active


//Check whether the vsftpd service on the controlled machine starts automatically
[root@localhost ansible]# ansible all -m shell -a 'systemctl is-enabled vsftpd'
192.168.25.130 | FAILED | rc=1 >>
disablednon-zero return code

//Set the vsftpd service on the controlled machine to start automatically
[root@localhost ansible]# ansible all -m service -a 'name=vsftpd enabled=yes'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "enabled": true,
    "name": "vsftpd",
    "status": {
        "ActiveEnterTimestamp": "Sat 2021-07-17 06:15:20 EDT",
        "ActiveEnterTimestampMonotonic": "34314422767",
        "ActiveExitTimestampMonotonic": "0",
        "ActiveState": "active",
        "After": "network.target systemd-journald.socket basic.target sysinit.target system.slice",
......

//Check whether the vsftpd service on the controlled machine starts automatically
[root@localhost ansible]# ansible all -m shell -a 'systemctl is-enabled vsftpd'
192.168.25.130 | CHANGED | rc=0 >>
enabled

//Stop the vsftpd service on the controlled machine
[root@localhost ansible]# ansible all -m service -a 'name=vsftpd state=stopped'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "name": "vsftpd",
    "state": "stopped",
    "status": {
        "ActiveEnterTimestamp": "Sat 2021-07-17 06:15:20 EDT",
        "ActiveEnterTimestampMonotonic": "34314422767",
        "ActiveExitTimestampMonotonic": "0",
        "ActiveState": "active",
        "After": "system.slice network.target sysinit.target systemd-journald.socket basic.target",
......

[root@localhost ansible]# ansible all -m shell -a 'systemctl is-active vsftpd'
192.168.25.130 | FAILED | rc=3 >>
inactivenon-zero return code

2.12 lineinfile module

  • The lineinfile module is used to ensure that a specific line is in a file, or to ensure that the specified text is deleted from the file (j that is, to ensure that the specified text does not exist in the file), and to replace "the text of a line" with a regular expression

Common parameters

  • path specifies the file to operate on
  • line specifies the text content
  • State setting status [when you want to delete the corresponding text, you need to set the state parameter to absent. The default value of state is present]
  • regexp uses regular expressions to match the corresponding lines [when replacing text, if multiple lines are matched, only the last matched line of text will be replaced; when deleting text, if multiple lines are matched, all lines will be deleted]
  • insertafter enables you to insert text after a "specified line"
//Change SELINUX=enforcing and in / etc/selinx/config to disabled
[root@localhost ansible]# ansible all -m lineinfile -a 'path=/etc/selinux/config regexp="^SELINUX=" line="SELINUX=disabled"'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line replaced"
}
[root@localhost ansible]# ansible all -m shell -a 'cat /etc/selinux/config'
192.168.25.130 | CHANGED | rc=0 >>

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted


//Insert hehe,xixi in managed host / opt/ll
[root@localhost ansible]# ansible all -m lineinfile -a 'path=/opt/ll line="hehe\nxixi"'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line added"
}
[root@localhost ansible]# ansible all -m shell -a 'cat /opt/ll'
192.168.25.130 | CHANGED | rc=0 >>
hell word
hehe
xixi

//Delete the line hehe in / opt/ll
[root@localhost ansible]# ansible all -m lineinfile -a 'path=/opt/ll state=absent regexp="hehe"'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "found": 1,
    "msg": "1 line(s) removed"
}
[root@localhost ansible]# ansible all -m shell -a 'cat /opt/ll'
192.168.25.130 | CHANGED | rc=0 >>
hell word
xixi


//Change owner and group
[root@node1 opt]# ll ll
-rw-r--r--. 1 root root 15 7 August 17:45 ll
[root@localhost ansible]# ansible all -m lineinfile -a 'path=/opt/ll owner=zhao group=zhao line=xix state=present'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "ownership, perms or SE linux context changed"
}
[root@node1 ~]# cd /opt/
[root@node1 opt]# ll ll
-rw-r--r--. 1 zhao zhao 19 7 August 17:52 ll

//Insert a row in / opt/ll on the managed host
[root@node1 opt]# cat ll
#Listen=80
hell word
xixi
[root@localhost ansible]# ansible all -m lineinfile -a 'path=/opt/ll regexp="^Listen" insertafter="#Listen" line=Listen=80'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line added"
}
[root@localhost ansible]# ansible all -m shell -a 'cat /opt/ll'
192.168.25.130 | CHANGED | rc=0 >>
#Listen=80
Listen=80
hell word
xixi

2.13 firewalld module

Firewalld specifies the released service, which must be queried on firewalld CMD -- get service

//Load the vsftpd service on the managed host into the firewall rules
[root@localhost ansible]# ansible all -m firewalld -a 'service=ftp permanent=yes state=enabled immediate=yes'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "Permanent and Non-Permanent(immediate) operation, Changed service ftp to enabled"
}


[root@node1 opt]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens160
  sources: 
  services: cockpit dhcpv6-client ftp ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

3LAMP separation deployment

First, write the IP addresses of the other three hosts into the manifest file of the management host

[root@localhost ansible]# vim inventory 
[root@localhost ansible]# cat inventory 
[webservers]
192.168.25.130  ansible_user=root ansible_password=1
192.168.25.140  ansible_user=root ansible_password=1
192.168.25.142  ansible_user=root ansibel_password=1

Do password free login for the other three hosts and test whether they can ping

[root@localhost ansible]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:vwTYVhpdEagFVrTJFdeIqwoKH/x3bzzGR1/xl6gS/Fc root@localhost
The key's randomart image is:
+---[RSA 3072]----+
|        o+o.*=.o |
|       . oo=... .|
|        .o*  .   |
|       o.+  .  . |
|   .  . S  .  . +|
|  . o .. =.  ..E+|
|   o + . .=o....o|
|    o . oo.+*.. .|
|       . .o+oo   |
+----[SHA256]-----+
[root@localhost ansible]# ssh-copy-id 192.168.25.140
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.25.140 (192.168.25.140)' can't be established.
ECDSA key fingerprint is SHA256:/SJbOLoOuH3estBrdxUtlQ56iKPhVSYumEVNVXmOye0.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.25.140's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '192.168.25.140'"
and check to make sure that only the key(s) you wanted were added.

[root@localhost ansible]# ansible 192.168.25.140 -m ping
192.168.25.140 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}


[root@localhost ansible]# ssh-copy-id 192.168.25.142
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.25.142 (192.168.25.142)' can't be established.
ECDSA key fingerprint is SHA256:/SJbOLoOuH3estBrdxUtlQ56iKPhVSYumEVNVXmOye0.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.25.142's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '192.168.25.142'"
and check to make sure that only the key(s) you wanted were added.

[root@localhost ansible]# ansible 192.168.25.142 -m ping
192.168.25.142 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

3.1 installing apache

Install apache

[root@localhost ansible]# ansible 192.168.25.130 -m yum -a 'name=httpd state=present'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: httpd-tools-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
        "Installed: mod_http2-1.11.3-3.module+el8.2.0+4377+dc421495.x86_64",
        "Installed: apr-util-openssl-1.6.1-6.el8.x86_64",
        "Installed: httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
        "Installed: apr-1.6.3-9.el8.x86_64",
        "Installed: apr-util-1.6.1-6.el8.x86_64",
        "Installed: redhat-logos-httpd-81.1-1.el8.noarch",
        "Installed: apr-util-bdb-1.6.1-6.el8.x86_64",
        "Installed: httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch"
    ]
}

[root@localhost ansible]# ansible 192.168.25.130 -m yum -a 'name=httpd-devel state=present'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: apr-devel-1.6.3-9.el8.x86_64",
        "Installed: httpd-devel-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
        "Installed: libdb-devel-5.3.28-37.el8.x86_64",
        "Installed: apr-util-devel-1.6.1-6.el8.x86_64",
        "Installed: expat-devel-2.2.5-3.el8.x86_64",
        "Installed: cyrus-sasl-devel-2.1.27-1.el8.x86_64",
        "Installed: openldap-devel-2.4.46-11.el8.x86_64"
    ]
}

Start apache

[root@localhost ansible]# ansible 192.168.25.130 -m service -a 'name=httpd state=started'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "name": "httpd",
    "state": "started",
    "status": {
        "ActiveEnterTimestampMonotonic": "0",
        "ActiveExitTimestampMonotonic": "0",
        "ActiveState": "inactive",
        "After": "-.mount sysinit.target network.target systemd-tmpfiles-setup.service nss-lookup.target remote-fs.target systemd-journald.socket system.slice tmp.mount httpd-init.service basic.target",

......

[root@localhost ansible]# ansible 192.168.25.130 -m shell -a 'systemctl is-active httpd'
192.168.25.130 | CHANGED | rc=0 >>
active

Set the httpd service to start automatically

[root@localhost ansible]# ansible 192.168.25.130 -m service -a 'name=httpd enabled=yes'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "enabled": true,
    "name": "httpd",
    "status": {
        "ActiveEnterTimestamp": "Sun 2021-07-18 03:38:14 EDT",
        "ActiveEnterTimestampMonotonic": "50817852436",
        "ActiveExitTimestampMonotonic": "0",
        "ActiveState": "active",
        "After": "httpd-init.service network.target systemd-journald.socket systemd-tmpfiles-setup.service nss-lookup.target tmp.mount basic.target -.mount sysinit.target system.slice remote-fs.target",

......

[root@localhost ansible]# ansible 192.168.25.130 -m shell -a 'systemctl is-enabled httpd'
192.168.25.130 | CHANGED | rc=0 >>
enabled

View service status

[root@localhost ansible]# ansible 192.168.25.130 -m shell -a 'systemctl status httpd'
192.168.25.130 | CHANGED | rc=0 >>
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2021-07-18 03:38:14 EDT; 5min ago
     Docs: man:httpd.service(8)
 Main PID: 62606 (httpd)
   Status: "Running, listening on: port 80"
    Tasks: 213 (limit: 11152)
   Memory: 23.7M
   CGroup: /system.slice/httpd.service
           ├─62606 /usr/sbin/httpd -DFOREGROUND
           ├─62628 /usr/sbin/httpd -DFOREGROUND
           ├─62629 /usr/sbin/httpd -DFOREGROUND
           ├─62630 /usr/sbin/httpd -DFOREGROUND
           └─62631 /usr/sbin/httpd -DFOREGROUND

7 March 18:37:58 node1 systemd[1]: Starting The Apache HTTP Server...
7 March 18:38:14 node1 httpd[62606]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::df4e:bd67:1a8c:e302. Set the 'ServerName' directive globally to suppress this message
7 March 18:38:14 node1 systemd[1]: Started The Apache HTTP Server.
7 March 18:38:24 node1 httpd[62606]: Server configured, listening on: port 80

View httpd port number 80

[root@localhost ansible]# ansible 192.168.25.130 -m raw -a 'ss -antl'
192.168.25.130 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    
LISTEN    0         128                0.0.0.0:111              0.0.0.0:*       
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*       
LISTEN    0         5                127.0.0.1:631              0.0.0.0:*       
LISTEN    0         128              127.0.0.1:6010             0.0.0.0:*       
LISTEN    0         128              127.0.0.1:6011             0.0.0.0:*       
LISTEN    0         128                   [::]:111                 [::]:*       
LISTEN    0         128                      *:80                     *:*       
LISTEN    0         128                   [::]:22                  [::]:*       
LISTEN    0         5                    [::1]:631                 [::]:*       
LISTEN    0         128                  [::1]:6010                [::]:*       
LISTEN    0         128                  [::1]:6011                [::]:*       
Shared connection to 192.168.25.130 closed.


Set http80 port for firewall release

[root@localhost ansible]# ansible 192.168.25.130 -m firewalld -a 'service=http permanent=yes state=enabled immediate=yes'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "Permanent and Non-Permanent(immediate) operation, Changed service http to enabled"
}

[root@localhost ansible]# ansible 192.168.25.130 -m firewalld -a 'service=https permanent=yes state=enabled immediate=yes'
192.168.25.130 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "Permanent and Non-Permanent(immediate) operation, Changed service https to enabled"
}


[root@node1 ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens160
  sources: 
  services: cockpit dhcpv6-client ftp http https ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 


Browser login

3.2 installing mysql

Install mysql

[root@localhost ansible]# ansible 192.168.25.140 -m yum -a 'name=mariadb  state=present'
192.168.25.140 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: mariadb-connector-c-3.0.7-1.el8.x86_64",
        "Installed: mariadb-connector-c-config-3.0.7-1.el8.noarch",
        "Installed: mariadb-3:10.3.17-1.module+el8.1.0+3974+90eded84.x86_64",
        "Installed: mariadb-common-3:10.3.17-1.module+el8.1.0+3974+90eded84.x86_64"
    ]
}

[root@localhost ansible]# ansible 192.168.25.140 -m yum -a 'name=mariadb-server  state=present'
192.168.25.140 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: mariadb-backup-3:10.3.17-1.module+el8.1.0+3974+90eded84.x86_64",
        "Installed: mariadb-errmsg-3:10.3.17-1.module+el8.1.0+3974+90eded84.x86_64",
        "Installed: mariadb-gssapi-server-3:10.3.17-1.module+el8.1.0+3974+90eded84.x86_64",
        "Installed: mariadb-server-3:10.3.17-1.module+el8.1.0+3974+90eded84.x86_64",
        "Installed: mariadb-server-utils-3:10.3.17-1.module+el8.1.0+3974+90eded84.x86_64",
        "Installed: perl-DBD-MySQL-4.046-3.module+el8.1.0+2938+301254e2.x86_64"
    ]
}


Start the mysql service and set the startup self startup

[root@localhost ansible]# ansible 192.168.25.140 -m service -a 'service=mariadb state=started'
192.168.25.140 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "name": "mariadb",
    "state": "started",
    "status": {
        "ActiveEnterTimestampMonotonic": "0",
        "ActiveExitTimestampMonotonic": "0",
        "ActiveState": "inactive",
        "After": "system.slice network.target systemd-tmpfiles-setup.service sysinit.target tmp.mount -.mount basic.target systemd-journald.socket",

......

[root@localhost ansible]# ansible 192.168.25.140 -m shell -a 'systemctl is-active mariadb'
192.168.25.140 | CHANGED | rc=0 >>
active

[root@localhost ansible]# ansible 192.168.25.140 -m service -a 'name=mariadb enabled=yes'
192.168.25.140 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "enabled": true,
    "name": "mariadb",
    "status": {
        "ActiveEnterTimestamp": "Sun 2021-07-18 04:08:13 EDT",
        "ActiveEnterTimestampMonotonic": "4287861883",
        "ActiveExitTimestampMonotonic": "0",
        "ActiveState": "active",
        "After": "basic.target tmp.mount system.slice network.target -.mount sysinit.target systemd-journald.socket systemd-tmpfiles-setup.service",

......


[root@localhost ansible]# ansible 192.168.25.140 -m shell -a 'systemctl is-enabled mariadb'
192.168.25.140 | CHANGED | rc=0 >>
enabled

View mysql service status

[root@localhost ansible]# ansible 192.168.25.140 -m shell -a 'netstat -tulp'
192.168.25.140 | CHANGED | rc=0 >>
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN      1159/sshd           
tcp        0      0 localhost:ipp           0.0.0.0:*               LISTEN      1161/cupsd          
tcp        0      0 localhos:x11-ssh-offset 0.0.0.0:*               LISTEN      2832/sshd: root@pts 
tcp        0      0 0.0.0.0:sunrpc          0.0.0.0:*               LISTEN      1/systemd           
tcp        0      0 node2:domain            0.0.0.0:*               LISTEN      2085/dnsmasq        
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN      1159/sshd           
tcp6       0      0 localhost:ipp           [::]:*                  LISTEN      1161/cupsd          
tcp6       0      0 localhos:x11-ssh-offset [::]:*                  LISTEN      2832/sshd: root@pts 
tcp6       0      0 [::]:mysql              [::]:*                  LISTEN      34191/mysqld        
tcp6       0      0 [::]:sunrpc             [::]:*                  LISTEN      1/systemd           
udp        0      0 0.0.0.0:58227           0.0.0.0:*                           995/avahi-daemon: r 
udp        0      0 node2:domain            0.0.0.0:*                           2085/dnsmasq        
udp        0      0 0.0.0.0:bootps          0.0.0.0:*                           2085/dnsmasq        
udp        0      0 0.0.0.0:sunrpc          0.0.0.0:*                           1/systemd           
udp        0      0 0.0.0.0:mdns            0.0.0.0:*                           995/avahi-daemon: r 
udp        0      0 localhost:323           0.0.0.0:*                           999/chronyd         
udp6       0      0 [::]:48692              [::]:*                              995/avahi-daemon: r 
udp6       0      0 [::]:sunrpc             [::]:*                              1/systemd           
udp6       0      0 [::]:mdns               [::]:*                              995/avahi-daemon: r 
udp6       0      0 localhost:323           [::]:*                              999/chronyd         

Database security settings

[root@node2 ~]# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): 
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] y
New password: 
Re-enter new password: 
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] n
 ... skipping.

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
[root@node2 ~]# 

Login database test

[root@node2 ~]# mysql -uroot -p1
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 15
Server version: 10.3.17-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.000 sec)

MariaDB [(none)]> 

3.3 installing PHP

Install PHP

[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: nginx-filesystem-1:1.14.1-9.module+el8.0.0+4108+af250afe.noarch",
        "Installed: apr-util-openssl-1.6.1-6.el8.x86_64",
        "Installed: php-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
        "Installed: php-cli-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
        "Installed: httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
        "Installed: php-common-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
        "Installed: mod_http2-1.11.3-3.module+el8.2.0+4377+dc421495.x86_64",
        "Installed: apr-1.6.3-9.el8.x86_64",
        "Installed: httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch",
        "Installed: apr-util-1.6.1-6.el8.x86_64",
        "Installed: redhat-logos-httpd-81.1-1.el8.noarch",
        "Installed: apr-util-bdb-1.6.1-6.el8.x86_64",
        "Installed: php-fpm-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
        "Installed: httpd-tools-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64"
    ]
}

Install common PHP modules

[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-gd state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: php-gd-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64"
    ]
}


[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-ldap state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: php-ldap-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64"
    ]
}


[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-odbc state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: php-pdo-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
        "Installed: php-odbc-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
        "Installed: unixODBC-2.3.7-1.el8.x86_64"
    ]
}


[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-pear state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: php-process-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
        "Installed: php-xml-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
        "Installed: php-pear-1:1.10.5-9.module+el8.1.0+3202+af5476b9.noarch"
    ]
}


[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-xml state=present'
192.168.25.142 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "msg": "Nothing to do",
    "rc": 0,
    "results": []
}

[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-xmlrpc state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: php-xmlrpc-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64"
    ]
}


[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-mbstring state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: php-mbstring-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64"
    ]
}


[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-snmp state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: net-snmp-1:5.8-14.el8.x86_64",
        "Installed: net-snmp-agent-libs-1:5.8-14.el8.x86_64",
        "Installed: lm_sensors-libs-3.4.0-21.20180522git70f7e08.el8.x86_64",
        "Installed: php-snmp-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
        "Installed: mariadb-connector-c-3.0.7-1.el8.x86_64",
        "Installed: mariadb-connector-c-config-3.0.7-1.el8.noarch"
    ]
}


[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-soap state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: php-soap-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64"
    ]
}


[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=php-bcmath state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: php-bcmath-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64"
    ]
}


[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=curl state=present'
192.168.25.142 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "msg": "Nothing to do",
    "rc": 0,
    "results": []
}

[root@localhost ansible]# ansible 192.168.25.142 -m yum -a 'name=curl-devel state=present'
192.168.25.142 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
        "Installed: libcurl-devel-7.61.1-12.el8.x86_64"
    ]
}

[root@node3 etc]# cd
[root@node3 ~]# mkdir -p /var/www/html
[root@node3 ~]# cd /var/www/html
[root@node3 html]# vim info.php
[root@node3 html]# cat info.php 

<?php
          phpinfo();
?>

Topics: Linux