AWS 代码部署失败的脚本由于权限

AWS Code Deploy Failing Scripts Due To Permissions

我在使用 AWS Code Deploy 部署时尝试 运行 一些脚本,但由于没有 运行 这些脚本的权限,它们从未 运行。

这是我的 appspec.yml 文件:

version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html
permissions:
  - object: /var/www/html/codedeploy-scripts
    owner: root
    mode: 777
    type:
      - directory
hooks:
  ApplicationStop:
    - location: codedeploy-scripts/application-stop
      timeout: 300
      runas: root
  BeforeInstall:
    - location: codedeploy-scripts/before-install
      timeout: 300
      runas: root
  AfterInstall:
    - location: codedeploy-scripts/after-install
      timeout: 600
      runas: root
  ApplicationStart:
    - location: codedeploy-scripts/application-start
      timeout: 300
      runas: root
  ValidateService:
    - location: codedeploy-scripts/validate-service
      timeout: 300
      runas: root

codedeploy-scripts 文件夹随应用一起部署,但我在该文件夹上设置的权限未设置。文件夹的权限总是重置为:

[ec2-user@ip-10-0-8-181 html]$ ls -al
total 156
drwxrwsr-x  7 ec2-user www   4096 Oct 13 16:36 .
drwxrwsr-x  3 ec2-user www   4096 Oct 13 15:01 ..
-rw-rw-r--  1 ec2-user www    740 Oct 13 16:28 appspec.yml
drwxr-sr-x  2 ec2-user www   4096 Oct 13 16:36 codedeploy-scripts
...

文件夹中的文件似乎具有可执行权限:

[ec2-user@ip-10-0-8-181 alio]$ ls -al codedeploy-scripts
total 28
drwxr-sr-x 2 ec2-user www 4096 Oct 13 16:36 .
drwxrwsr-x 7 ec2-user www 4096 Oct 13 16:36 ..
-rwxr-xr-x 1 ec2-user www  343 Oct 13 16:28 after-install
-rwxr-xr-x 1 ec2-user www   12 Oct 13 16:28 application-start
-rwxr-xr-x 1 ec2-user www   12 Oct 13 16:28 application-stop
-rwxr-xr-x 1 ec2-user www  889 Oct 13 16:28 before-install
-rwxr-xr-x 1 ec2-user www   12 Oct 13 16:28 validate-service

为什么没有使用我在 appspec 文件中设置的权限部署代码。 codedeploy-scripts 文件夹应该有 777 权限,但它从来没有。

这是我在 /var/log/aws/codedeploy-agent/codedeploy-agent.log 中为每个脚本得到的错误:

2015-10-13 16:36:23 WARN  [codedeploy-agent(9918)]: InstanceAgent::Plugins::CodeDeployPlugin::HookExecutor: Script at specified location: codedeploy-scripts/validate-service is not executable.  Trying to make it executable.

如有任何帮助,我们将不胜感激。

代理直接从提取的存档包中执行脚本,而不是从您可能使用 files 部分复制它们的任意位置执行脚本。您需要在 S3 或 Git 存储库中的存档中设置执行位。

你拥有的是这样做的:

  • 将所有文件复制到/var/www/html
  • 将目录对 /var/www/html/codedeploy-scripts 内容的权限设置为 777,而不是目录本身(参见 appspec.yml reference)。这也会受到 umask 的影响,您可能正在设置 /etc/profile.
  • 从存档根执行生命周期事件(当它们发生时)的每个脚本。所以你的 ValidateSerivce 脚本是来自 <deployment-archive-root>/codedeploy-scripts/validate-service 的 运行 而不是来自 /var/www/html/codedeploy-scripts/validate-service

注意:ApplicationStop 是特殊的,因为它在下载新的新存档包之前运行。

如果没有更多详细信息,我将无法说明为什么将您的脚本设置为可执行文件可以解决您的问题,但是除了您看到的日志语句之外,接受的答案不应该解决任何问题。

仔细看日志:

2015-10-13 16:36:23 WARN  [codedeploy-agent(9918)]: InstanceAgent::Plugins::CodeDeployPlugin::HookExecutor: Script at specified location: codedeploy-scripts/validate-service is not executable.  Trying to make it executable.

这只是警告,不是错误。 Code Deploy 代理注意到您的 validate_service.sh 脚本不可执行,它正在“尝试 使其可执行”。如果我们查看 relevant Code Deploy agent code,您会看到代理将 chmod +x 脚本本身。

当您将脚本设置为可执行时,您只是消除了此警告,它不应该影响任何其他内容。回顾 L106 中的 Code Deploy 代理代码,如果代理无法使您的脚本可执行,您会在日志中看到错误。

要回答您关于权限的问题,您的配置有误 appspec.yml。当你说:

  permissions:
    - object: /var/www/html/codedeploy-scripts
      owner: root
      mode: 777
      type:
        - directory

您要让 Code Deploy 将 /var/www/html/codedeploy-scripts 中类型为 "directory" 的所有文件设置为具有权限 777.

您在 codedeploy-scripts 下的所有脚本都是 "file" 类型(不是 "directory"),这就是为什么没有设置它们的权限,并且权限只适用于文件 在您指定的目录下,这就是未设置codedeploy-scripts目录权限的原因。

这是 the AWS docs 中 appspec.yml 权限的 type 选项的描述:

type – Optional. The types of objects to apply the specified permissions to. This can be set to file or directory. If file is specified, the permissions will be applied only to files that are immediately contained within object after the copy operation (and not to object itself). If directory is specified, the permissions will be recursively applied to all directories/folders that are anywhere within object after the copy operation (but not to object itself).

我想详细说明 Jonathan Turpie 提到的一个问题,它可能会造成非常奇怪的情况。

来自 ApplicationStop 上的文档:

This deployment lifecycle event occurs even before the application revision is downloaded. ... The AppSpec file and scripts used for this deployment lifecycle event are from the previous successfully deployed application revision.

现在想象一下这种情况:

  1. 使用拙劣的 ApplicationStop 脚本权限部署了修订版。由于使用了以前的版本,部署仍然很顺利。
  2. 一个新的修订被推送并且失败了 ApplicationStop 步骤(因为现在它试图执行步骤 1 中的拙劣脚本)。
  3. 您发现自己的错误,修复代码,发布新的修订版,但仍然失败并出现同样的错误!

目前无法通过部署新代码来修复错误。你只有两个选择:

  1. 在部署设置中启用 "Ignore Stop failures"(例如使用 --ignore-application-stop-failures CLI 标志 [1])
  2. 手动修复之前成功部署的根目录中的文件权限。

这涉及任何停止脚本失败,当然不仅仅是权限。

[1] https://docs.aws.amazon.com/cli/latest/reference/deploy/create-deployment.html

解决权限问题:

希望您位于所有脚本 .sh 文件所在的根目录中:

  1. chmod +x ./*.sh

这使得所有 .sh 文件都可执行

  1. 添加一些脚本 change_permissions.sh 并在文件中添加以下内容:
#!/bin/bash
chmod -R 777 /var/www/html/

这将为您的目标文件夹提供 - /var/www/html/ 可执行权限。

  1. 最后 asspec.yml 文件以某种方式添加以下内容:
  BeforeInstall:
  - location: change_permissions.sh
    timeout: 6
    runas: root

这将在 运行 时在您的 ec2 实例中对文件应用可执行权限。