Ansible一键布署LAMP
1、环境规划
1.1、主机规划
[root@ansible-control ansible-env]# cat /etc/ansible/hosts [php-server] 192.168.10.17 [mysql-server] 192.168.10.19 [nginx-server] 192.168.10.18 [lnmp:children] php-server mysql-server nginx-server
1.2、使用Roles规划目录
# 创建Roles相关目录 mkdir -p /opt/lnmp/group_vars mkdir -p /opt/lnmp/base/{tasks,files,templates,handlers} mkdir -p /opt/lnmp/nginx/{tasks,files,templates,handlers} mkdir -p /opt/lnmp/php/{tasks,files,templates,handlers} mkdir -p /opt/lnmp/mysql/{tasks,files,templates,handlers} # 目录结构 /opt/lnmp/ ├── base │ ├── files │ ├── handlers │ ├── tasks │ └── templates ├── group_vars ├── mysql │ ├── files │ ├── handlers │ ├── tasks │ └── templates ├── nginx │ ├── files │ ├── handlers │ ├── tasks │ └── templates ├── php │ ├── files │ ├── handlers │ ├── tasks │ └── templates
1.4、编写入口yaml
cat > /opt/lnmp/run.yaml << 'EOF' - hosts: all roles: - role: base - hosts: php-server roles: - role: php - hosts: nginx-server roles: - role: nginx - hosts: mysql-server roles: - role: mysql EOF
1.5、初始化所有主机
1.5.1、base目录结构
[root@ansible-control lnmp]# tree base/ base/ ├── files ├── handlers ├── tasks │ └── main.yaml └── templates
1.5.2、base/task/base.yaml
cat > /opt/lnmp/base/tasks/main.yaml << 'EOF' - name: set base yum repo yum_repository: name: CentOS-Base baseurl: http://mirrors.aliyun.com/centos/7.9.2009/os/x86_64/ description: "Base repo" enabled: yes gpgkey: http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7 gpgcheck: true state: present - name: epel yum repo yum_repository: name: epel baseurl: http://mirrors.aliyun.com/epel/7/x86_64/ description: "epel repo" enabled: no gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 gpgcheck: false state: present - name: install base software yum: name: - tree - vim - lrzsz - unzip - psmisc - net-tools - ntpdate state: present - name: stop firewalld systemd: name: firewalld state: stopped enabled: no - name: disable selinux selinux: state: disabled - name: change time zone command: timedatectl set-timezone Asia/Shanghai - name: config sync time cron: name: ali sync time minute: "*/1" job: "/sbin/ntpdate ntp5.aliyun.com &>/dev/null" EOF
2、安装Nginx
2.1、软件下载地址
http://nginx.org/download/nginx-1.12.2.tar.gz
2.2、目录结构
[root@ansible-control lnmp]# tree nginx/ nginx/ ├── files │ ├── index.php │ └── nginx-1.12.2.tar.gz ├── handlers │ └── main.yaml ├── tasks │ └── main.yaml └── templates ├── nginx.conf.j2 └── nginx.service
2.3、nginx/task/main.yaml
[root@ansible-control lnmp]# cat nginx/tasks/main.yaml - name: groupadd tags: nginx_install group: name: nginx - name: useradd tags: nginx_install user: name: nginx group: nginx shell: /sbin/nologin create_home: no - name: install lib devel tags: nginx_install yum: name: - pcre - pcre-devel - openssl - openssl-devel - gcc - gcc-c++ state: installed - name: cp nginx_src file tags: nginx_install copy: src: nginx-1.12.2.tar.gz dest: /root/nginx-1.12.2.tar.gz backup: yes - name: unarchive nginx src tags: nginx_install unarchive: src: /root/nginx-1.12.2.tar.gz dest: /root/ remote_src: yes - name: compile nginx and install tags: nginx_install shell: cd "{{nginx_pkg}}" && ./configure --user="{{user}}" --group="{{user}}" --prefix="{{prefix}}" --with-http_ssl_module --with-http_stub_status_module --with-stream && make && make install - name: copy nginx.conf tags: - nginx_install template: src: nginx.conf.j2 dest: /usr/local/nginx-1.12.2/conf/nginx.conf backup: yes notify: restart nginx - name: configure nginx server tags: nginx_install template: src: nginx.service dest: /usr/lib/systemd/system/nginx.service mode: 0755 - name: change permission tags: - nginx_install file: path: "{{prefix}}" state: directory owner: nginx recurse: yes - name: start nginx service tags: - nginx_start - nginx_install systemd: name: nginx state: started enabled: yes - name: www dir tags: - php_install file: path: /var/www state: directory owner: nginx mode: 0755 - name: test php page tags: - php_install copy: src: index.php dest: /var/www owner: nginx mode: 0755
2.4、group_vars/nginx-server
[root@ansible-control lnmp]# cat group_vars/nginx-server user: nginx prefix: /usr/local/nginx-1.12.2 nginx_pkg: /root/nginx-1.12.2 php_ip: 192.168.10.17
2.5、handlers/main.yaml
[root@ansible-control lnmp]# cat nginx/handlers/main.yaml - name: restart nginx systemd: name: nginx state: restarted
2.6、template/nginx.conf.j2
[root@ansible-control lnmp]# cat nginx/templates/nginx.conf.j2 worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root /var/www; index index.html index.htm index.php; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { root /var/www; fastcgi_pass {{php_ip}}:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi.conf; } } }
2.7、templates/nginx.service
[root@ansible-control lnmp]# cat nginx/templates/nginx.service [Unit] Description=nginx - high performance web server After=network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile={{ prefix }}/logs/nginx.pid ExecStartPre={{ prefix }}/sbin/nginx -t -c {{ prefix }}/conf/nginx.conf ExecStart={{ prefix }}/sbin/nginx -c {{ prefix }}/conf/nginx.conf ExecReload={{ prefix }}/sbin/nginx -s reload ExecStop={{ prefix }}/sbin/nginx -s stop ExecQuit={{ prefix }}/sbin/nginx -s quit PrivateTmp=true [Install] WantedBy=multi-user.target
3、安装MySQL
3.1、注意事项
# 被控制主机需要安装此包 yum install MySQL-python # ansible 控制主机 yum install mysql-devel pip3 install mysqlclient
# mysql 首次初始化数据库时,需要手动介入,设置好root帐号和密码
mysqld --initialize --user=mysql --datadir=/usr/local/mysql/data/
3.2、软件下载地址
https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.41-el7-x86_64.tar.gz
3.3、目录结构
[root@ansible-control lnmp]# tree mysql mysql ├── files │ └── mysql-5.7.41-el7-x86_64.tar.gz ├── handlers ├── tasks │ └── main.yaml └── templates ├── my.cnf.j2 ├── mysql.server └── mysql.service
3.4、tasks/main.yaml
[root@ansible-control lnmp]# cat mysql/tasks/main.yaml - name: groupadd tags: mysql_install group: name: mysql - name: useradd tags: mysql_install user: name: mysql group: mysql shell: /sbin/nologin create_home: no - name: install mysql lib-devel tags: mysql_install yum: name: - cmake - ncurses-devel - autoconf - zlib - zlib-devel - name: unzip mysql tar tags: - mysql_install unarchive: src: mysql-5.7.41-el7-x86_64.tar.gz dest: /usr/local - name: create software link tags: - mysql_install file: src: /usr/local/mysql-5.7.41-el7-x86_64 dest: /usr/local/mysql state: link - name: mysql config my.cnf tags: mysql_install template: src: my.cnf.j2 dest: /etc/my.cnf backup: yes - name: mkdir mysql logs tags: - mysql_install file: path: "{{ mysql_logs }}" state: directory owner: mysql - name: copy mysql.server tags: - mysql_install template: src: mysql.server dest: "{{ mysql_base }}/mysql.server" mode: 755 backup: yes - name: copy mysql.service tags: - mysql_install template: src: mysql.service dest: /lib/systemd/system/mysql.service backup: yes - name: tags: - mysql_start systemd: name: mysql state: started - name: tags: - mysql_start community.mysql.mysql_db: login_host: "localhost" login_port: "{{port}}" login_user: "{{login_user}}" login_unix_socket: "{{mysql_sock}}" login_password: "{{login_password}}" encoding: "utf8" name: "{{db_name}}" state: present - name: Create database user tags: - mysql_start community.mysql.mysql_user: login_host: "localhost" login_port: "{{port}}" login_user: "{{login_user}}" login_password: "{{login_password}}" login_unix_socket: "{{mysql_sock}}" name: "{{db_name}}" host: '%' password: "{{db_pwd}}" priv: 'wpdb.*:ALL' state: present
3.5、templates/my.cnf.j2
[root@ansible-control lnmp]# cat mysql/templates/my.cnf.j2 [mysqld] port = {{port}} bind-address = 0.0.0.0 symbolic-links=0 skip-name-resolve slave-skip-errors = 1032,1062,1050 socket={{mysql_sock}} pid-file ={{mysql_pid}} datadir={{mysql_data}} binlog_cache_size = 1M max_binlog_cache_size = 2M max_binlog_size = 10M expire_logs_days = 7 key_buffer_size = 16M read_buffer_size = 2M read_rnd_buffer_size = 2M bulk_insert_buffer_size = 2M innodb_buffer_pool_size=512M innodb_buffer_pool_instances=1 innodb_autoextend_increment=128M innodb_log_file_size=512M innodb_flush_log_at_trx_commit=2 innodb_buffer_pool_size=512M max_allowed_packet=64M binlog_format="MIXED" character-set-server=utf8 [mysql] default-character-set=utf8 socket={{mysql_sock}} [mysqld_safe] log-error={{mysql_logs}}/mysql_safe.err pid-file ={{mysql_pid}}
3.6、templates/mysql.server

[root@ansible-control lnmp]# cat mysql/templates/mysql.server #!/bin/sh # Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB # This file is public domain and comes with NO WARRANTY of any kind # MySQL daemon start/stop script. # Usually this is put in /etc/init.d (at least on machines SYSV R4 based # systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql. # When this is done the mysql server will be started when the machine is # started and shut down when the systems goes down. # Comments to support chkconfig on RedHat Linux # chkconfig: 2345 64 36 # description: A very fast and reliable SQL database engine. # Comments to support LSB init script conventions ### BEGIN INIT INFO # Provides: mysql # Required-Start: $local_fs $network $remote_fs # Should-Start: ypbind nscd ldap ntpd xntpd # Required-Stop: $local_fs $network $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop MySQL # Description: MySQL is a very fast and reliable SQL database engine. ### END INIT INFO # If you install MySQL on some other places than /usr/local/mysql, then you # have to do one of the following things for this script to work: # # - Run this script from within the MySQL installation directory # - Create a /etc/my.cnf file with the following information: # [mysqld] # basedir=<path-to-mysql-installation-directory> # - Add the above to any other configuration file (for example ~/.my.ini) # and copy my_print_defaults to /usr/bin # - Add the path to the mysql-installation-directory to the basedir variable # below. # # If you want to affect other MySQL variables, you should make your changes # in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files. # If you change base dir, you must also change datadir. These may get # overwritten by settings in the MySQL configuration files. basedir={{mysql_base}} datadir={{mysql_data}} # Default value, in seconds, afterwhich the script should timeout waiting # for server start. # Value here is overriden by value in my.cnf. # 0 means don't wait at all # Negative numbers mean to wait indefinitely service_startup_timeout=900 # Lock directory for RedHat / SuSE. lockdir='/var/lock/subsys' lock_file_path="$lockdir/mysql" # The following variables are only set for letting mysql.server find things. # Set some defaults mysqld_pid_file_path= if test -z "$basedir" then basedir=/usr/local/mysql bindir=/usr/local/mysql/bin if test -z "$datadir" then datadir=/usr/local/mysql/data fi sbindir=/usr/local/mysql/bin libexecdir=/usr/local/mysql/bin else bindir="$basedir/bin" if test -z "$datadir" then datadir="$basedir/data" fi sbindir="$basedir/sbin" libexecdir="$basedir/libexec" fi # datadir_set is used to determine if datadir was set (and so should be # *not* set inside of the --basedir= handler.) datadir_set= # # Use LSB init script functions for printing messages, if possible # lsb_functions="/lib/lsb/init-functions" if test -f $lsb_functions ; then . $lsb_functions else log_success_msg() { echo " SUCCESS! $@" } log_failure_msg() { echo " ERROR! $@" } fi PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin" export PATH mode=$1 # start or stop [ $# -ge 1 ] && shift other_args="$*" # uncommon, but needed when called from an RPM upgrade action # Expected: "--skip-networking --skip-grant-tables" # They are not checked here, intentionally, as it is the resposibility # of the "spec" file author to give correct arguments only. case `echo "testing\c"`,`echo -n testing` in *c*,-n*) echo_n= echo_c= ;; *c*,*) echo_n=-n echo_c= ;; *) echo_n= echo_c='\c' ;; esac parse_server_arguments() { for arg do case "$arg" in --basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'` bindir="$basedir/bin" if test -z "$datadir_set"; then datadir="$basedir/data" fi sbindir="$basedir/sbin" libexecdir="$basedir/libexec" ;; --datadir=*) datadir=`echo "$arg" | sed -e 's/^[^=]*=//'` datadir_set=1 ;; --pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; --service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; esac done } wait_for_pid () { verb="$1" # created | removed pid="$2" # process ID of the program operating on the pid-file pid_file_path="$3" # path to the PID file. i=0 avoid_race_condition="by checking again" while test $i -ne $service_startup_timeout ; do case "$verb" in 'created') # wait for a PID-file to pop into existence. test -s "$pid_file_path" && i='' && break ;; 'removed') # wait for this PID-file to disappear test ! -s "$pid_file_path" && i='' && break ;; *) echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path" exit 1 ;; esac # if server isn't running, then pid-file will never be updated if test -n "$pid"; then if kill -0 "$pid" 2>/dev/null; then : # the server still runs else # The server may have exited between the last pid-file check and now. if test -n "$avoid_race_condition"; then avoid_race_condition="" continue # Check again. fi # there's nothing that will affect the file. log_failure_msg "The server quit without updating PID file ($pid_file_path)." return 1 # not waiting any more. fi fi echo $echo_n ".$echo_c" i=`expr $i + 1` sleep 1 done if test -z "$i" ; then log_success_msg return 0 else log_failure_msg return 1 fi } # Get arguments from the my.cnf file, # the only group, which is read from now on is [mysqld] if test -x "$bindir/my_print_defaults"; then print_defaults="$bindir/my_print_defaults" else # Try to find basedir in /etc/my.cnf conf=/etc/my.cnf print_defaults= if test -r $conf then subpat='^[^=]*basedir[^=]*=\(.*\)$' dirs=`sed -e "/$subpat/!d" -e 's//\1/' $conf` for d in $dirs do d=`echo $d | sed -e 's/[ ]//g'` if test -x "$d/bin/my_print_defaults" then print_defaults="$d/bin/my_print_defaults" break fi done fi # Hope it's in the PATH ... but I doubt it test -z "$print_defaults" && print_defaults="my_print_defaults" fi # # Read defaults file from 'basedir'. If there is no defaults file there # check if it's in the old (depricated) place (datadir) and read it from there # extra_args="" if test -r "$basedir/my.cnf" then extra_args="-e $basedir/my.cnf" fi parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server` # # Set pid file if not given # if test -z "$mysqld_pid_file_path" then mysqld_pid_file_path=$datadir/`hostname`.pid else case "$mysqld_pid_file_path" in /* ) ;; * ) mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;; esac fi case "$mode" in 'start') # Start daemon # Safeguard (relative paths, core dumps..) cd $basedir echo $echo_n "Starting MySQL" if test -x $bindir/mysqld_safe then # Give extra arguments to mysqld with the my.cnf file. This script # may be overwritten at next upgrade. $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null & wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$? # Make lock for RedHat / SuSE if test -w "$lockdir" then touch "$lock_file_path" fi exit $return_value else log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)" fi ;; 'stop') # Stop daemon. We use a signal here to avoid having to know the # root password. if test -s "$mysqld_pid_file_path" then # signal mysqld_safe that it needs to stop touch "$mysqld_pid_file_path.shutdown" mysqld_pid=`cat "$mysqld_pid_file_path"` if (kill -0 $mysqld_pid 2>/dev/null) then echo $echo_n "Shutting down MySQL" kill $mysqld_pid # mysqld should remove the pid file when it exits, so wait for it. wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$? else log_failure_msg "MySQL server process #$mysqld_pid is not running!" rm "$mysqld_pid_file_path" fi # Delete lock for RedHat / SuSE if test -f "$lock_file_path" then rm -f "$lock_file_path" fi exit $return_value else log_failure_msg "MySQL server PID file could not be found!" fi ;; 'restart') # Stop the service and regardless of whether it was # running or not, start it again. if $0 stop $other_args; then $0 start $other_args else log_failure_msg "Failed to stop running server, so refusing to try to start." exit 1 fi ;; 'reload'|'force-reload') if test -s "$mysqld_pid_file_path" ; then read mysqld_pid < "$mysqld_pid_file_path" kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL" touch "$mysqld_pid_file_path" else log_failure_msg "MySQL PID file could not be found!" exit 1 fi ;; 'status') # First, check to see if pid file exists if test -s "$mysqld_pid_file_path" ; then read mysqld_pid < "$mysqld_pid_file_path" if kill -0 $mysqld_pid 2>/dev/null ; then log_success_msg "MySQL running ($mysqld_pid)" exit 0 else log_failure_msg "MySQL is not running, but PID file exists" exit 1 fi else # Try to find appropriate mysqld process mysqld_pid=`pidof $libexecdir/mysqld` # test if multiple pids exist pid_count=`echo $mysqld_pid | wc -w` if test $pid_count -gt 1 ; then log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)" exit 5 elif test -z $mysqld_pid ; then if test -f "$lock_file_path" ; then log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists" exit 2 fi log_failure_msg "MySQL is not running" exit 3 else log_failure_msg "MySQL is running but PID file could not be found" exit 4 fi fi ;; *) # usage basename=`basename "$0"` echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL server options ]" exit 1 ;; esac exit 0
3.7、templates/mysql.service
[root@ansible-control lnmp]# cat mysql/templates/mysql.service [Unit] Description=MySQL server daemon Documentation=/home/application/mysql/man After=network.target [Service] Type=forking ExecStart={{mysql_base}}/mysql.server start ExecReload={{mysql_base}}/mysql.server reload ExecStop={{mysql_base}}/mysql.server stop Restart={{mysql_base}}/mysql.server restart PrivateTmp=True [Install] WantedBy=multi-user.target
3.8、group_vars/mysql-server
[root@ansible-control lnmp]# cat group_vars/mysql-server port: 3306 mysql_base: /usr/local/mysql mysql_data: /usr/local/mysql/data user: msyql mysql_pid: /usr/local/mysql/data/mysqld_safe.pid mysql_sock: /usr/local/mysql/data/mysql.sock mysql_logs: /usr/local/mysql/logs login_user: root login_password: root1234 mysql_sock: /usr/local/mysql/data/mysql.sock
4、安装php
4.1、软件下载地址
https://www.php.net/distributions/php-7.4.16.tar.gz
4.2、目录结构
[root@ansible-control lnmp]# tree php/ php/ ├── files │ ├── index.php │ ├── mysql-5.7.41-el7-x86_64.tar.gz │ └── php-7.4.16.tar.gz ├── handlers ├── tasks │ └── main.yaml └── templates ├── php-fpm.conf.default ├── php-fpm.service ├── php.ini-production ├── www.conf.default └── www.conf.j2
4.3、tasks/main.yaml
[root@ansible-control lnmp]# ll php/tasks/main.yaml -rw-r--r-- 1 root root 2613 Mar 1 23:25 php/tasks/main.yaml (ansible-env) [root@ansible-control lnmp]# cat php/tasks/main.yaml - name: php install lib-devel tags: php_install yum: name: - gcc - gcc-c++ - freetype - freetype-devel - libpng - libpng-devel - libxml2-devel - libmcrypt - libmcrypt-devel - mhash - libxml2 - libxml2-devel - mcrypt - zlib - zlib-devel - libjpeg - libjpeg-devel - sqlite-devel - oniguruma - oniguruma-devel - expat-devel enablerepo: epel state: installed - name: unzip mysql tar tags: - php_install unarchive: src: mysql-5.7.41-el7-x86_64.tar.gz dest: /usr/local - name: create software link tags: - php_install file: src: /usr/local/mysql-5.7.41-el7-x86_64 dest: /usr/local/mysql state: link - name: unzip php tar tags: - php_install unarchive: src: php-7.4.16.tar.gz dest: /root/ - name: php compile install tags: php_install shell: "cd {{install_dir}} && ./configure --prefix={{prefix}} --with-config-file-path={{prefix}}/etc/ --with-mysqli={{mysql_base}}/bin/mysql_config --with-pdo-mysql={{mysql_base}} --with-expat --with-jpeg --with-freetype --enable-soap --enable-mbstring=all --enable-sockets --enable-gd --enable-fpm --with-fpm-user=php --with-fpm-group=php && make && make install" - name: groupadd tags: - php_install group: name: php - name: useradd tags: - php_install user: name: php group: php shell: /sbin/nologin create_home: no - name: copy php.ini tags: - php_install - copy_phpini template: src: php.ini-production dest: /usr/local/php-7.4.16/etc/php.ini backup: yes - name: copy php-fpm tags: - php_install - copy_phpini template: src: php-fpm.conf.default dest: /usr/local/php-7.4.16/etc/php-fpm.conf backup: yes - name: copy www.conf tags: - php_install - copy_phpini template: src: www.conf.j2 dest: /usr/local/php-7.4.16/etc/php-fpm.d/www.conf backup: yes - name: configure php-fpm server tags: - php_install template: src: php-fpm.service dest: /usr/lib/systemd/system/php-fpm.service mode: 755 - name: systemctl daemon-reload tags: - php_install shell: systemctl daemon-reload - name: start php-fpm tags: - php_install systemd: name: php-fpm state: started enabled: yes - name: www dir tags: - php_install file: path: /var/www state: directory owner: php mode: 0755 - name: test php page tags: - php_install copy: src: index.php dest: /var/www owner: php mode: 0755
4.3、templates/php-fpm.conf.default
# 文件的来源 scp root@192.168.10.17:/usr/local/php-7.4.16/etc/php-fpm.conf.default /opt/lnmp/php/templates/ [root@ansible-control php]# cat templates/php-fpm.conf.default ;;;;;;;;;;;;;;;;;;;;; ; FPM Configuration ; ;;;;;;;;;;;;;;;;;;;;; ; All relative paths in this configuration file are relative to PHP's install ; prefix (/usr/local/php-7.4.16). This prefix can be dynamically changed by using the ; '-p' argument from the command line. ;;;;;;;;;;;;;;;;;; ; Global Options ; ;;;;;;;;;;;;;;;;;; [global] ; Pid file ; Note: the default prefix is /usr/local/php-7.4.16/var ; Default Value: none pid = run/php-fpm.pid ; Error log file ; If it's set to "syslog", log is sent to syslogd instead of being written ; into a local file. ; Note: the default prefix is /usr/local/php-7.4.16/var ; Default Value: log/php-fpm.log ;error_log = log/php-fpm.log ; syslog_facility is used to specify what type of program is logging the ; message. This lets syslogd specify that messages from different facilities ; will be handled differently. ; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON) ; Default Value: daemon ;syslog.facility = daemon ; syslog_ident is prepended to every message. If you have multiple FPM ; instances running on the same server, you can change the default value ; which must suit common needs. ; Default Value: php-fpm ;syslog.ident = php-fpm ; Log level ; Possible Values: alert, error, warning, notice, debug ; Default Value: notice ;log_level = notice ; Log limit on number of characters in the single line (log entry). If the ; line is over the limit, it is wrapped on multiple lines. The limit is for ; all logged characters including message prefix and suffix if present. However ; the new line character does not count into it as it is present only when ; logging to a file descriptor. It means the new line character is not present ; when logging to syslog. ; Default Value: 1024 ;log_limit = 4096 ; Log buffering specifies if the log line is buffered which means that the ; line is written in a single write operation. If the value is false, then the ; data is written directly into the file descriptor. It is an experimental ; option that can potentionaly improve logging performance and memory usage ; for some heavy logging scenarios. This option is ignored if logging to syslog ; as it has to be always buffered. ; Default value: yes ;log_buffering = no ; If this number of child processes exit with SIGSEGV or SIGBUS within the time ; interval set by emergency_restart_interval then FPM will restart. A value ; of '0' means 'Off'. ; Default Value: 0 ;emergency_restart_threshold = 0 ; Interval of time used by emergency_restart_interval to determine when ; a graceful restart will be initiated. This can be useful to work around ; accidental corruptions in an accelerator's shared memory. ; Available Units: s(econds), m(inutes), h(ours), or d(ays) ; Default Unit: seconds ; Default Value: 0 ;emergency_restart_interval = 0 ; Time limit for child processes to wait for a reaction on signals from master. ; Available units: s(econds), m(inutes), h(ours), or d(ays) ; Default Unit: seconds ; Default Value: 0 ;process_control_timeout = 0 ; The maximum number of processes FPM will fork. This has been designed to control ; the global number of processes when using dynamic PM within a lot of pools. ; Use it with caution. ; Note: A value of 0 indicates no limit ; Default Value: 0 ; process.max = 128 ; Specify the nice(2) priority to apply to the master process (only if set) ; The value can vary from -19 (highest priority) to 20 (lowest priority) ; Note: - It will only work if the FPM master process is launched as root ; - The pool process will inherit the master process priority ; unless specified otherwise ; Default Value: no set ; process.priority = -19 ; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. ; Default Value: yes ;daemonize = yes ; Set open file descriptor rlimit for the master process. ; Default Value: system defined value ;rlimit_files = 1024 ; Set max core size rlimit for the master process. ; Possible Values: 'unlimited' or an integer greater or equal to 0 ; Default Value: system defined value ;rlimit_core = 0 ; Specify the event mechanism FPM will use. The following is available: ; - select (any POSIX os) ; - poll (any POSIX os) ; - epoll (linux >= 2.5.44) ; - kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0) ; - /dev/poll (Solaris >= 7) ; - port (Solaris >= 10) ; Default Value: not set (auto detection) ;events.mechanism = epoll ; When FPM is built with systemd integration, specify the interval, ; in seconds, between health report notification to systemd. ; Set to 0 to disable. ; Available Units: s(econds), m(inutes), h(ours) ; Default Unit: seconds ; Default value: 10 ;systemd_interval = 10 ;;;;;;;;;;;;;;;;;;;; ; Pool Definitions ; ;;;;;;;;;;;;;;;;;;;; ; Multiple pools of child processes may be started with different listening ; ports and different management options. The name of the pool will be ; used in logs and stats. There is no limitation on the number of pools which ; FPM can handle. Your system will tell you anyway :) ; Include one or more files. If glob(3) exists, it is used to include a bunch of ; files from a glob(3) pattern. This directive can be used everywhere in the ; file. ; Relative path can also be used. They will be prefixed by: ; - the global prefix if it's been set (-p argument) ; - /usr/local/php-7.4.16 otherwise include={{prefix}}/etc/php-fpm.d/*.conf
4.4、templates/php-fpm.service
[root@ansible-control php]# cat templates/php-fpm.service [Unit] Description=The PHP FastCGI Process Manager After=syslog.target network.target [Service] Type=forking PIDFile={{prefix}}/var/run/php-fpm.pid ExecStart={{prefix}}/sbin/php-fpm ExecReload=/bin/kill -USR2 $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target
4.5、templates/php.ini-production
scp root@192.168.10.17:/root/php-7.4.16/php.ini-production /opt/lnmp/php/templates/

[root@ansible-control php]# cat templates/php.ini-production | grep -Ev '^;|^$' [PHP] engine = On short_open_tag = Off precision = 14 output_buffering = 4096 zlib.output_compression = Off implicit_flush = Off unserialize_callback_func = serialize_precision = -1 disable_functions = disable_classes = zend.enable_gc = On zend.exception_ignore_args = On expose_php = On max_execution_time = 30 max_input_time = 60 memory_limit = 128M error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT display_errors = Off display_startup_errors = Off log_errors = On log_errors_max_len = 1024 ignore_repeated_errors = Off ignore_repeated_source = Off report_memleaks = On variables_order = "GPCS" request_order = "GP" register_argc_argv = Off auto_globals_jit = On post_max_size = 8M auto_prepend_file = auto_append_file = default_mimetype = "text/html" default_charset = "UTF-8" doc_root = user_dir = enable_dl = Off file_uploads = On upload_max_filesize = 2M max_file_uploads = 20 allow_url_fopen = On allow_url_include = Off default_socket_timeout = 60 [CLI Server] cli_server.color = On [Date] [filter] [iconv] [imap] [intl] [sqlite3] [Pcre] [Pdo] [Pdo_mysql] pdo_mysql.default_socket= [Phar] [mail function] SMTP = localhost smtp_port = 25 mail.add_x_header = Off [ODBC] odbc.allow_persistent = On odbc.check_persistent = On odbc.max_persistent = -1 odbc.max_links = -1 odbc.defaultlrl = 4096 odbc.defaultbinmode = 1 [MySQLi] mysqli.max_persistent = -1 mysqli.allow_persistent = On mysqli.max_links = -1 mysqli.default_port = 3306 mysqli.default_socket = mysqli.default_host = mysqli.default_user = mysqli.default_pw = mysqli.reconnect = Off [mysqlnd] mysqlnd.collect_statistics = On mysqlnd.collect_memory_statistics = Off [OCI8] [PostgreSQL] pgsql.allow_persistent = On pgsql.auto_reset_persistent = Off pgsql.max_persistent = -1 pgsql.max_links = -1 pgsql.ignore_notice = 0 pgsql.log_notice = 0 [bcmath] bcmath.scale = 0 [browscap] [Session] session.save_handler = files session.use_strict_mode = 0 session.use_cookies = 1 session.use_only_cookies = 1 session.name = PHPSESSID session.auto_start = 0 session.cookie_lifetime = 0 session.cookie_path = / session.cookie_domain = session.cookie_httponly = session.cookie_samesite = session.serialize_handler = php session.gc_probability = 1 session.gc_divisor = 1000 session.gc_maxlifetime = 1440 session.referer_check = session.cache_limiter = nocache session.cache_expire = 180 session.use_trans_sid = 0 session.sid_length = 26 session.trans_sid_tags = "a=href,area=href,frame=src,form=" session.sid_bits_per_character = 5 [Assertion] zend.assertions = -1 [COM] [mbstring] [gd] [exif] [Tidy] tidy.clean_output = Off [soap] soap.wsdl_cache_enabled=1 soap.wsdl_cache_dir="/tmp" soap.wsdl_cache_ttl=86400 soap.wsdl_cache_limit = 5 [sysvshm] [ldap] ldap.max_links = -1 [dba] [opcache] [curl] [openssl] [ffi]
4.6、templates/www.conf.j2
scp root@192.168.10.17:/usr/local/php-7.4.16/etc/php-fpm.d/www.conf.default .
[root@ansible-control php]# cat templates/www.conf.j2 [www] user = {{ user }} group = {{ user }} listen = {{ansible_default_ipv4.address}}:9000 pm = dynamic pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3
4.7、group_vars/php-server
[root@ansible-control lnmp]# cat group_vars/php-server install_dir: /root/php-7.4.16 prefix: /usr/local/php-7.4.16 mysql_base: /usr/local/mysql user: php nginx_ip: 192.168.10.18
5、group_vars/all
[root@ansible-control lnmp]# cat group_vars/all db_name: wpdb db_user: wp db_pwd: 123456 mysql_ip: 192.168.10.19
6、wordpress布署
6.1、软件下载
https://cn.wordpress.org/latest-zh_CN.tar.gz
6.2、目录结构
[root@ansible-control lnmp]# tree wordpress/ wordpress/ ├── files │ └── wordpress-6.1.1-zh_CN.tar.gz ├── handlers ├── tasks │ └── main.yaml └── templates └── wp-config-sample.php
6.3、wordpress/tasks/main.yaml
[root@ansible-control lnmp]# cat wordpress/tasks/main.yaml - name: unzip wordpress tags: worldpress unarchive: src: wordpress-6.1.1-zh_CN.tar.gz dest: /var/www owner: php - name: copy wp-config.php tags: worldpress template: src: wp-config-sample.php dest: /var/www/wordpress/wp-config.php owner: php mode: 0755
6.4、准备wp-config-sample.php
scp root@192.168.10.17:/var/www/wordpress/wp-config-sample.php .
6.5、安装wordpress
http://192.168.10.18/wordpress/wp-admin/install.php
6.6、安装成功
7、整个项目完整的目录结构
[root@ansible-control lnmp]# tree /opt/lnmp/ /opt/lnmp/ ├── base │ ├── files │ ├── handlers │ ├── tasks │ │ └── main.yaml │ └── templates ├── group_vars │ ├── all │ ├── mysql-server │ ├── nginx-server │ └── php-server ├── mysql │ ├── files │ │ └── mysql-5.7.41-el7-x86_64.tar.gz │ ├── handlers │ ├── tasks │ │ └── main.yaml │ └── templates │ ├── my.cnf.j2 │ ├── mysql.server │ └── mysql.service ├── nginx │ ├── files │ │ ├── index.php │ │ └── nginx-1.12.2.tar.gz │ ├── handlers │ │ └── main.yaml │ ├── tasks │ │ └── main.yaml │ └── templates │ ├── nginx.conf.j2 │ └── nginx.service ├── php │ ├── files │ │ ├── index.php │ │ ├── mysql-5.7.41-el7-x86_64.tar.gz │ │ └── php-7.4.16.tar.gz │ ├── handlers │ ├── tasks │ │ └── main.yaml │ └── templates │ ├── php-fpm.conf.default │ ├── php-fpm.service │ ├── php.ini-production │ ├── www.conf.default │ └── www.conf.j2 ├── run.yaml └── wordpress ├── files │ └── wordpress-6.1.1-zh_CN.tar.gz ├── handlers ├── tasks │ └── main.yaml └── templates └── wp-config-sample.php
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义