前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何在Ubuntu 14.04上使用Ansible部署高级PHP应用程序

如何在Ubuntu 14.04上使用Ansible部署高级PHP应用程序

原创
作者头像
圣人惠好可爱
修改于 2018-09-26 09:17:18
修改于 2018-09-26 09:17:18
10.9K00
代码可运行
举报
运行总次数:0
代码可运行

介绍

在本教程中,我们将介绍如何设置SSH密钥以支持代码部署/发布工具,配置系统防火墙,配置和配置数据库(包括密码!),以及设置任务调度程序(crons)和队列守护进程。本教程结束时的目标是让您拥有一个具有上述高级配置的完全可用的PHP应用程序服务器

与上一个教程一样,我们将使用Laravel框架作为示例PHP应用程序。但是,如果您已拥有自己的框架和应用程序,则可以轻松修改这些说明以支持其他框架和应用程序。

先决条件

在本教程中,我们将使用Ansible在Ubuntu 14.04 Droplet上安装和配置Nginx,PHP和其他服务。本教程以Ansible的基本知识为基础。

要学习本教程,您需要:

  • 我们将用于配置和部署我们的PHP应用程序的任何大小的Ubuntu 14.04 腾讯云CVM。整个教程将引用本机的your_server_ipIP地址。
  • 一个Ubuntu 14.04 CVM将用于Ansible。这是您将在本教程的整个过程中登录的CVM。
  • 为两个CVM配置的有sodo权限的非root用户。(一台已经设置好可以使用sudo命令的非root账号的Ubuntu服务器,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。)
  • Ansible CVM的SSH密钥授权在PHP部署CVM上登录。

第1步 - 切换应用程序存储库

在此步骤中,我们将Git存储库更新为稍微自定义的示例存储库。

由于默认的Laravel安装不需要我们将在本教程中设置的高级功能,因此我们将现有存储库从标准存储库切换到添加了一些调试代码的示例存储库,只是为了显示何时工作正常。我们将使用的存储库位于https://github.com/do-community/do-ansible-adv-php

如果您还没有这样做,请将目录更改为ansible-php

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cd ~/ansible-php/

打开我们现有的剧本进行编辑。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nano php.yml

查找并更新“Clone git repository”任务,看起来像这样。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Clone git repository
  git: >
    dest=/var/www/laravel
    repo=https://github.com/do-community/do-ansible-adv-php
    update=yes
    version=example
  sudo: yes
  sudo_user: www-data
  register: cloned

保存并运行剧本。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansible-playbook php.yml --ask-sudo-pass

运行完毕后,请在Web浏览器中访问您的服务器(即http://your_server_ip/)。您应该看到一条消息“无法找到驱动程序”

这意味着我们已成功换出示例存储库的默认存储库,但应用程序无法连接到数据库。这是我们期望在这里看到的,我们将在本教程的后面安装和设置数据库。

步骤2 - 设置SSH密钥以进行部署

在此步骤中,我们将设置可用于应用程序代码部署脚本的SSH密钥。

虽然Ansible非常适合维护配置和设置服务器和应用程序,但EnvoyRocketeer等工具通常用于将代码更改推送到服务器并远程运行应用程序命令。大多数这些工具都需要SSH连接才能直接访问应用程序安装。在我们的例子中,这意味着我们需要为www-data用户配置SSH密钥。

我们将需要您希望从中推送代码的用户的公钥文件。此文件通常位于~/.ssh/id_rsa.pub。将该文件复制到该ansible-php目录中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cp ~/.ssh/id_rsa.pub ~/ansible-php/deploykey.pub

我们可以使用Ansible authorized_key模块在其中安装我们的公钥/var/www/.ssh/authorized_keys,这将允许部署工具连接和访问我们的应用程序。配置只需要知道密钥的位置,使用查找,以及需要安装密钥的用户(www-data在我们的例子中)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Copy public key into /var/www
  authorized_key: user=www-data key="{{ lookup('file', 'deploykey.pub') }}"

我们还需要设置www-data用户的shell,因此我们实际上可以登录。否则,SSH将允许连接,但不会向用户显示shell。这可以使用user模块完成,并将shell设置为/bin/bash(或您首选的shell)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Set www-data user shell
  user: name=www-data shell=/bin/bash

现在,打开剧本进行编辑以添加新任务。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nano php.yml

将上述任务添加到您的php.yml剧本中; 文件的末尾应与以下内容匹配。添加内容为后2段以“-”开头的文字。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
. . .- name: Configure nginx
    template: src=nginx.conf dest=/etc/nginx/sites-available/default
    notify:
      - restart php5-fpm
      - restart nginx
​
  - name: Copy public key into /var/www
    authorized_key: user=www-data key="{{ lookup('file', 'deploykey.pub') }}"- name: Set www-data user shell
    user: name=www-data shell=/bin/bash
​
  handlers:. . .

保存并运行剧本。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansible-playbook php.yml --ask-sudo-pass

当Ansible完成时,您应该能够使用该www-data用户来SSH 。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ssh www-data@your_server_ip

如果您成功登录,它正在运行!您现在可以通过输入logout或按CTRL + D进行注销。

我们不需要将该连接用于本教程中的任何其他步骤,但是如果您正在设置其他工具(如上所述)或者根据需要进行常规调试和应用程序维护,它将非常有用。

第3步 - 配置防火墙

在此步骤中,我们将在服务器上配置防火墙,以仅允许HTTP和SSH连接。

Ubuntu 14.04 默认安装了UFW(Uncomplicated Firewall),Ansible支持该ufw模块。它具有许多强大的功能,并且设计得尽可能简单。它非常适合只需要打开几个端口的自包含Web服务器。在我们的例子中,我们希望打开端口80(HTTP)和端口22(SSH)。您可能还需要端口443用于HTTPS。

ufw模块具有许多不同的选项,可执行不同的任务。我们需要执行的不同任务是:

  1. 默认情况下启用UFW并拒绝所有传入流量。
  2. 打开SSH端口,但速率限制它以防止暴力攻击。
  3. 打开HTTP端口。

这可以分别通过以下任务完成。

新的Ansible任务

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Enable UFW
  ufw: direction=incoming policy=deny state=enabled
​
- name: UFW limit SSH
  ufw: rule=limit port=ssh
​
- name: UFW open HTTP
  ufw: rule=allow port=http

和以前一样,打开php.yml文件进行编辑。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nano php.yml

将上述任务添加到剧本中; 文件的末尾应与以下内容匹配。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
. . .- name: Copy public key into /var/www
    authorized_key: user=www-data key="{{ lookup('file', 'deploykey.pub') }}"- name: Set www-data user shell
    user: name=www-data shell=/bin/bash
​
  - name: Enable UFW
    ufw: direction=incoming policy=deny state=enabled
​
  - name: UFW limit SSH
    ufw: rule=limit port=ssh
​
  - name: UFW open HTTP
    ufw: rule=allow port=http
​
  handlers:. . .

保存并运行剧本。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansible-playbook php.yml --ask-sudo-pass

成功完成后,您仍然可以通过SSH(使用Ansible)或HTTP连接到您的服务器; 其他端口现在将被阻止。

您可以通过运行此命令随时验证UFW的状态:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansible php --sudo --ask-sudo-pass -m shell -a "ufw status verbose"

分解上面的Ansible命令:

  • ansible:运行原始的Ansible任务,没有剧本。
  • php:针对此组中的主机运行任务。
  • --sudo:运行命令为sudo
  • --ask-sudo-pass:提示输入sudo密码。
  • -m shell:运行shell模块。
  • -a "ufw status verbose":要传递给模块的选项。因为它是一个shell命令,我们直接传递原始命令(即ufw status verbose)而没有任何key=value选项。

它应该返回这样的东西。

UFW状态输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
your_server_ip | success | rc=0 >>
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
​
To                         Action      From
--                         ------      ----
22                         LIMIT IN    Anywhere
80                         ALLOW IN    Anywhere
22 (v6)                    LIMIT IN    Anywhere (v6)
80 (v6)                    ALLOW IN    Anywhere (v6)

第4步 - 安装MySQL包

在这一步中,我们将为我们的应用程序设置一个MySQL数据库。

(自建服务器难免会遇到这样的问题,配置SSL很麻烦,虽然对一部分人来说这也是一种乐趣,但是如果您在生产环境使用,我还是建议您直接使用云关系型数据库,云关系型数据库让您在云中轻松部署、管理和扩展的关系型数据库,提供安全可靠、伸缩灵活的按需云数据库服务。腾讯云关系型数据库提供 MySQL、SQL ServerMariaDBPostgreSQL 数据库引擎,并针对数据库引擎的性能进行了优化。云关系型数据库是一种高度可用的托管服务,提供容灾、备份、恢复、监控、迁移等数据库运维全套解决方案,可将您从耗时的数据库管理任务中解放出来,让您有更多时间专注于您的应用和业务。)

第一步是确保在我们的服务器上安装MySQL,只需将所需的包添加到我们的playbook顶部的安装包任务即可。我们需要的包有mysql-servermysql-clientphp5-mysql。我们还需要python-mysqldbAnsible可以与MySQL通信。

在我们添加软件包时,我们需要重新启动nginxphp5-fpm确保应用程序可以使用新软件包。在这种情况下,我们需要MySQL可用于PHP,因此它可以连接到数据库。

Ansible的一个奇妙之处在于您可以修改任何任务并重新运行您的剧本,并且将应用更改。这包括选项列表,就像我们对apt任务一样。

和以前一样,打开php.yml文件进行编辑。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nano php.yml

找到install packages任务,并更新它以包含上面的包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
. . .- name: install packages
  apt: name={{ item }} update_cache=yes state=latest
  with_items:
    - git
    - mcrypt
    - nginx
    - php5-cli
    - php5-curl
    - php5-fpm
    - php5-intl
    - php5-json
    - php5-mcrypt
    - php5-sqlite
    - sqlite3
    - mysql-server
    - mysql-client
    - php5-mysql
    - python-mysqldb
  notify:
    - restart php5-fpm
    - restart nginx
​
. . .

保存并运行剧本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansible-playbook php.yml --ask-sudo-pass

第5步 - 设置MySQL数据库

在这一步中,我们将为我们的应用程序创建一个MySQL数据库。

Ansible可以通过直接与MySQL mysql_-prefaced模块(例如mysql_dbmysql_user)。该mysql_db模块提供了一种确保具有特定名称的数据库的方法,因此我们可以使用这样的任务来创建数据库。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Create MySQL DB
  mysql_db: name=laravel state=present

我们还需要一个具有已知密码的有效用户帐户,以允许我们的应用程序连接到数据库。一种方法是在本地生成密码并将其保存在我们的Ansible playbook中,但这是不安全的,并且有更好的方法。

我们将在服务器上使用Ansible生成密码,并在需要的地方直接使用。要生成密码,我们将使用makepasswd命令行工具,并要求输入32个字符的密码。因为makepasswd在Ubuntu上不是默认的,我们还需要将它添加到包列表中。

我们还会告诉Ansible记住命令的输出(即密码),以便我们稍后可以在我们的剧本中使用它。但是,因为Ansible不知道它是否已经运行了shell命令,所以我们还会在运行该命令时创建一个文件。Ansible将检查文件是否存在,如果存在,它将假定该命令已经运行并且不会再次运行它。

任务看起来像这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Generate DB password
  shell: makepasswd --chars=32
  args:
    creates: /var/www/laravel/.dbpw
  register: dbpwd

接下来,我们需要使用我们指定的密码创建实际的MySQL数据库用户。这是使用mysql_user模块完成的,我们可以使用stdout我们在密码生成任务中定义的变量选项来获取shell命令的原始输出,如下所示:dbpwd.stdout

mysql_user命令接受用户的名称和所需的权限。在我们的例子中,我们想要创建一个被调用的用户,laravel并为他们提供laravel表的完全权限。我们还需要告诉任务仅在dbpwd变量发生变化时才运行,这只会在密码生成任务运行时运行。

任务应如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Create MySQL User
  mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present
  when: dbpwd.changed

把它们放在一起,打开php.yml文件进行编辑,这样我们就可以添加上述任务了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nano php.yml

首先,找到install packages任务,并更新它以包含该makepasswd包。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
. . .- name: install packages
  apt: name={{ item }} update_cache=yes state=latest
  with_items:
    - git
    - mcrypt
    - nginx
    - php5-cli
    - php5-curl
    - php5-fpm
    - php5-intl
    - php5-json
    - php5-mcrypt
    - php5-sqlite
    - sqlite3
    - mysql-server
    - mysql-client
    - php5-mysql
    - python-mysqldb
    - makepasswd
  notify:
    - restart php5-fpm
    - restart nginx
​
. . .

然后,在底部添加密码生成,MySQL数据库创建和用户创建任务。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
. . .- name: UFW limit SSH
    ufw: rule=limit port=ssh
​
  - name: UFW open HTTP
    ufw: rule=allow port=http
​
  - name: Create MySQL DB
    mysql_db: name=laravel state=present
​
  - name: Generate DB password
    shell: makepasswd --chars=32
    args:
      creates: /var/www/laravel/.dbpw
    register: dbpwd
​
  - name: Create MySQL User
    mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present
    when: dbpwd.changed
​
  handlers:. . .

不要运行剧本了!您可能已经注意到虽然我们已经创建了MySQL用户和数据库,但我们还没有对密码做任何事情。我们将在下一步中介绍它。shell在Ansible中使用任务时,记住在运行任务之前完成处理任务输出/结果的整个工作流程以避免必须手动登录和重置状态,这一点非常重要。

第6步 - 为数据库配置PHP应用程序

在此步骤中,我们将MySQL数据库密码保存到.env应用程序的文件中。

就像我们在上一个教程中所做的那样,我们将更新.env文件以包含我们新创建的数据库凭据。默认情况下,Laravel的.env文件包含以下行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

我们可以按DB_HOST原样保留该行,但是将使用以下任务更新其他三行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: set DB_DATABASE
  lineinfile: dest=/var/www/laravel/.env regexp='^DB_DATABASE=' line=DB_DATABASE=laravel
​
- name: set DB_USERNAME
  lineinfile: dest=/var/www/laravel/.env regexp='^DB_USERNAME=' line=DB_USERNAME=laravel
​
- name: set DB_PASSWORD
  lineinfile: dest=/var/www/laravel/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }}
  when: dbpwd.changed

正如我们对MySQL用户创建任务所做的那样,我们使用生成的密码变量(dbpwd.stdout)来使用密码填充文件,并添加了when选项以确保它仅在dbpwd更改时运行。

现在,因为在我们添加密码生成任务之前.env文件已经存在,我们需要将密码保存到另一个文件。生成任务可以查找该文件的存在(我们已在任务中设置)。我们还将使用sudosudo_user选项告诉Ansible以www-data用户身份创建文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Save dbpw file
  lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present
  sudo: yes
  sudo_user: www-data
  when: dbpwd.changed

打开php.yml文件进行编辑。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nano php.yml

将上述任务添加到剧本中; 文件的末尾应与以下内容匹配。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
. . .

  - name: Create MySQL User
    mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present
    when: dbpwd.changed

  - name: set DB_DATABASE
    lineinfile: dest=/var/www/laravel/.env regexp='^DB_DATABASE=' line=DB_DATABASE=laravel

  - name: set DB_USERNAME
    lineinfile: dest=/var/www/laravel/.env regexp='^DB_USERNAME=' line=DB_USERNAME=laravel

  - name: set DB_PASSWORD
    lineinfile: dest=/var/www/laravel/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }}
    when: dbpwd.changed

  - name: Save dbpw file
    lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present
    sudo: yes
    sudo_user: www-data
    when: dbpwd.changed

  handlers:

. . .

再次,不要运行剧本了!在我们运行剧本之前,我们还有一个步骤要完成。

第7步 - 迁移数据库

在此步骤中,我们将运行数据库迁移以设置数据库表。

在Laravel中,这是通过在Laravel目录中运行migrate命令(即php artisan migrate --force)来完成的。请注意,我们添加了--force标志,因为production环境需要它。

执行此操作的Ansible任务如下所示。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  - name: Run artisan migrate
    shell: php /var/www/laravel/artisan migrate --force
    sudo: yes
    sudo_user: www-data
    when: dbpwd.changed

现在是时候更新我们的剧本了。打开php.yml文件进行编辑。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nano php.yml

将上述任务添加到剧本中; 文件的末尾应与以下内容匹配。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
. . .

  - name: Save dbpw file
    lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes   state=present
    sudo: yes
    sudo_user: www-data
    when: dbpwd.changed

  - name: Run artisan migrate
    shell: php /var/www/laravel/artisan migrate --force
    sudo: yes
    sudo_user: www-data
    when: dbpwd.changed

  handlers:

. . .

最后,我们可以保存并运行剧本。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansible-playbook php.yml --ask-sudo-pass

完成执行后,在浏览器中刷新页面,您会看到一条消息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Queue: NO
Cron: NO

这意味着数据库已正确设置并按预期工作,但我们尚未设置cron任务或队列守护程序。

第8步 - 配置cron任务

在此步骤中,我们将设置需要配置的任何cron任务。

Cron任务是在设定的时间表上运行的命令,可用于为您的应用程序执行任意数量的任务,例如执行维护任务或发送电子邮件活动更新 - 基本上任何需要定期完成而无需手动用户干预的任务。Cron任务可以像每分钟一样频繁地运行,也可以根据需要不频繁地运行。

Laravel附带默认调用的名为schedule:run的Artisan命令,该命令旨在每分钟运行并在应用程序中执行定义的计划任务。这意味着如果我们的应用程序利用此功能,我们只需要添加一个cron任务。

Ansible有一个cron包含许多不同选项的模块,可直接转换为您可以通过cron配置的不同选项:

  • job:要执行的命令。如果state = present则需要。
  • minutehourdaymonth,和weekday:在分钟,小时,天,月,或当作业应当运行,分别是星期几。
  • special_timerebootyearlyannuallymonthlyweeklydailyhourly):特殊时间规范的绰号。

默认情况下,它将创建一个每分钟运行的任务,这正是我们想要的。这意味着我们想要的任务看起来像这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Laravel Scheduler
  cron: >
    job="run-one php /var/www/laravel/artisan schedule:run 1>> /dev/null 2>&1"
    state=present
    user=www-data
    name="php artisan schedule:run"

run-one命令是Ubuntu中的一个小帮助程序,可确保命令仅运行一次。这意味着如果先前的schedule:run命令仍在运行,则不会再次运行。这有助于避免cron任务在循环中被锁定的情况,并且随着时间的推移,在服务器资源耗尽之前,会启动相同任务的越来越多的实例。

和以前一样,打开php.yml文件进行编辑。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nano php.yml

将上述任务添加到剧本中; 文件的末尾应与以下内容匹配。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
. . .

  - name: Run artisan migrate
    shell: php /var/www/laravel/artisan migrate --force
    sudo: yes
    sudo_user: www-data
    when: dbpwd.changed

  - name: Laravel Scheduler
    cron: >
      job="run-one php /var/www/laravel/artisan schedule:run 1>> /dev/null 2>&1"
      state=present
      user=www-data
      name="php artisan schedule:run"

  handlers:

. . .

保存并运行剧本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansible-playbook php.yml --ask-sudo-pass

现在,在浏览器中刷新页面。在一分钟内,它将更新为这样。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Queue: NO
Cron: YES

这意味着cron正在后台正常工作。作为示例应用程序的一部分,有一个cron作业每分钟运行一次,更新数据库中的状态条目,以便应用程序知道它正在运行。

步骤9 - 配置队列守护程序

与步骤8中的名为schedule:run的Artisan命令一样,Laravel还带有一个可以使用queue:work --daemonArtisan命令启动的队列工作程序。在此步骤中,我们将为Laravel配置队列守护程序worker。

队列工作者与cron作业类似,因为他们在后台运行任务。不同之处在于应用程序通过用户执行的操作或通过cron作业调度的任务将作业推送到队列中。队列任务由工作者一次执行一次,并且当在队列中找到它们时将按需处理。队列任务通常用于需要时间执行的工作,例如发送电子邮件或对外部服务进行API调用。

schedule:run命令不同,这不是每分钟都需要运行的命令。相反,它需要不断在后台运行作为守护进程。一种常见的方法是使用像supervisord这样的第三方软件包,但该方法需要了解如何配置和管理所述系统。使用cron和run-one命令实现它的方法要简单得多。

我们将创建一个cron条目来启动队列工作守护程序,并用run-one它来运行它。这意味着cron将在第一次运行时启动该进程,并且当工作程序运行时,任何后续的cron运行都将被忽略run-one。一旦工作程序停止,run-one将允许该命令再次运行,并且队列工作程序将再次启动。这是一种非常简单易用的方法,使您无需学习如何配置和使用其他工具。

考虑到所有这些,我们将创建另一个cron任务来运行我们的队列工作者。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- name: Laravel Queue Worker
  cron: >
    job="run-one php /var/www/laravel/artisan queue:work --daemon --sleep=30 --delay=60 --tries=3 1>> /dev/null 2>&1"
    state=present
    user=www-data
    name="Laravel Queue Worker"

和以前一样,打开php.yml文件进行编辑。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nano php.yml

将上述任务添加到剧本中; 文件的末尾应与以下内容匹配:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
. . .

  - name: Laravel Scheduler
    cron: >
      job="run-one php /var/www/laravel/artisan schedule:run 1>> /dev/null 2>&1"
      state=present
      user=www-data
      name="php artisan schedule:run"

  - name: Laravel Queue Worker
    cron: >
      job="run-one php /var/www/laravel/artisan queue:work --daemon --sleep=30 --delay=60 --tries=3 1>> /dev/null 2>&1"
      state=present
      user=www-data
      name="Laravel Queue Worker"

  handlers:
. . .

保存并运行剧本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansible-playbook php.yml --ask-sudo-pass

像以前一样,在浏览器中刷新页面。一分钟后,它将更新为如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Queue: YES
Cron: YES

这意味着队列工作者正在后台正常工作。我们在上一步中启动的cron作业将作业推送到队列中。此作业在运行时更新数据库以显示其正在运行。

我们现在有一个工作示例Laravel应用程序,其中包括正常运行的cron作业和队列工作程序。

结论

本教程介绍了使用Ansible部署PHP应用程序时的一些更高级的主题。所有使用的任务都可以轻松修改,以适应大多数PHP应用程序(取决于他们的具体要求),它应该为您的应用程序设置自己的Playbooks提供一个很好的起点。

我们没有使用单个SSH命令作为本教程的一部分(除了检查www-data用户登录之外),并且所有内容(包括MySQL用户密码)都已自动设置。完成本教程后,您的应用程序已准备就绪,并支持推送代码更新的工具。

更多Ubuntu教程请前往腾讯云+社区学习更多知识。

参考文献:《How To Deploy an Advanced PHP Application Using Ansible on Ubuntu 14.04》

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
[ Java学习基础 ] Java异常处理
一、异常概述   异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error;如果你用System.out.println(11/0),那么你是因为你用0做了除数,会抛出 java.lang.ArithmeticException 的异常。   异常发生的原因有很多,通常包含以下几大类: 用户输入了非法数据。 要打开的文件不存在。 网络通信时连接中断,或者JVM内存溢出。   这些异常有的是因为用
Kevin_Zhang
2018/05/22
2K0
【Java 基础篇】Java 异常处理详解
在软件开发中,错误和异常是常见的情况。Java 引入了异常处理机制,使得开发人员可以更加优雅地处理错误和异常情况。本文将详细介绍 Java 异常的概念、类型、处理方式和最佳实践,并提供一些示例代码。
繁依Fanyi
2023/10/12
5120
Java 异常处理下篇:11 个异常处理最佳实践
👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
Lorin 洛林
2023/12/15
5995
如何使用Java异常处理来优雅地处理各种异常情况?
在Java编程中,异常处理是一个非常重要的话题。良好的异常处理可以帮助我们更好地调试和排除代码中的错误,同时也可以提高代码的可读性、可维护性和稳定性。本文将详细介绍如何使用Java异常处理来优雅地处理各种异常情况。
网络技术联盟站
2023/06/03
5020
【Java 基础篇】Java线程异常处理详解
在多线程编程中,异常处理是一个至关重要的方面,它决定了你的多线程应用程序的稳定性和可靠性。在本篇博客中,我们将深入探讨Java中的线程异常处理,包括线程抛出的异常类型、如何捕获和处理异常以及最佳实践。
繁依Fanyi
2023/10/12
4810
【Java 基础篇】Java线程异常处理详解
Java 异常处理下篇:11 个异常处理最佳实践
闻说社
2024/11/11
1990
Java 异常处理下篇:11 个异常处理最佳实践
Java大学问——优雅地处理异常
你有没有这样的印象,当你想要更新一款 APP 的时候,它的更新日志里总有这么一两句描述:
本人秃顶程序员
2019/05/05
5770
Java大学问——优雅地处理异常
【译】11条Java异常处理的最佳实践
在之前关于Java异常的文章中,已经探讨过suppressed exceptions和Java Exceptions Tutorial 两个方面的内容。要想在实际项目中正确处理Java异常,你应该熟练掌握一些Java异常处理的最佳实践。
阿杜
2018/08/06
4320
【译】11条Java异常处理的最佳实践
Java异常处理
异常:在Java语言中,将程序执行中发生的不正常情况称为“异常” 开发过程中的语法错误和逻辑错误不是异常)
Java_慈祥
2024/08/06
1230
Java异常处理
Java异常体系中的秘密
相信大家每天都在使用Java异常机制,也相信大家对try-catch-finally执行流程烂熟于胸。本文将介绍Java异常机制的一些细节问题,这些问题虽然很小,但对代码性能、可读性有着较为重要的作用
大闲人柴毛毛
2018/03/29
1.1K0
Java异常体系中的秘密
Java异常面试题(2020最新版)
Java异常架构与异常关键字Java异常简介Java异常架构1. Throwable2. Error(错误)3. Exception(异常)运行时异常编译时异常
用户7886150
2020/12/18
8070
Java基础系列6:深入理解Java异常体系
该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架。
说故事的五公子
2019/11/15
5930
【Java ——异常机制详解】
异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程。Java通 过API中Throwable类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的 错误条件。当条件生成时,错误将引发异常。
奥耶可乐冰
2024/05/31
2840
【Java】异常处理:从基础到进阶
在编程中,异常(Exception)是指程序在运行过程中程序的错误或者意外情况,它会导致程序的控制流发生改变。通常,异常发生时程序会停止正常执行,直到找到能够处理该异常的代码或者终止程序的执行。
Yui_
2025/01/27
1850
走进异常类的世界,自定义业务异常类实现指南
引言 学习Java异常类,需掌握其基础概念,如try-catch语句、throw与throws关键字。通过实例理解异常层次结构,区分已检查与未检查异常。实践编写自定义异常类,并在项目中灵活运用异常处理机制,以提高代码的健壮性和可读性。
学无止尽5
2024/11/29
2170
走进异常类的世界,自定义业务异常类实现指南
【JAVA-Day68】异常处理的奥秘:深度解析 Java try-catch-finally 机制,高效应对异常问题
在软件开发中,异常处理是保障程序稳定性的重要一环。本文将深入研究 Java 中的 try-catch-finally 机制,通过对每个环节的详细解析和实际案例演示,帮助读者更好地理解和应用异常处理的核心知识点。
默 语
2024/11/20
1420
【JAVA-Day68】异常处理的奥秘:深度解析 Java try-catch-finally 机制,高效应对异常问题
Java异常:从初学者到高手,掌握异常处理的技巧!
在上期文章中,我们讨论了Java基础中的数据类型和控制流结构。这些是任何编程语言的核心部分,决定了程序的逻辑和数据处理方式。今天,我们将迈向Java开发中的另一个重要主题——异常处理。
bug菌
2024/08/16
1830
Java异常:从初学者到高手,掌握异常处理的技巧!
Java 异常处理:构建稳健的程序防线
在 Java 编程的世界里,异常处理犹如一座坚固的堡垒,守护着程序的稳定性与可靠性。有效的异常处理机制不仅能够帮助我们及时发现并解决程序运行过程中出现的问题,还能提升用户体验,避免因未处理的异常导致程序崩溃。本文将深入探讨 Java 异常处理的方方面面,包括异常的基本概念、类型、处理方式以及最佳实践。
编程小白狼
2024/12/31
1780
Java异常Exception详解
将可能出现异常的代码块选中->快捷键 ctrl + alt + t -> 选中 try-catch
timerring
2023/04/21
5570
Java异常Exception详解
详解Java中的checked异常和unchecked异常
在这篇Java异常教程中,我们会学到Java中的异常(Exception)是什么、checked异常和unchecked的区别是什么,并且还会学到关于Java中处理checked异常的一些很好的实践。
小诸葛
2020/11/25
4.2K0
详解Java中的checked异常和unchecked异常
推荐阅读
相关推荐
[ Java学习基础 ] Java异常处理
更多 >
LV.2
这个人很懒,什么都没有留下~
目录
  • 先决条件
  • 第1步 - 切换应用程序存储库
  • 步骤2 - 设置SSH密钥以进行部署
  • 第3步 - 配置防火墙
  • 第4步 - 安装MySQL包
  • 第5步 - 设置MySQL数据库
  • 第6步 - 为数据库配置PHP应用程序
  • 第7步 - 迁移数据库
  • 第8步 - 配置cron任务
  • 步骤9 - 配置队列守护程序
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档