Help us learn about your current experience with the documentation. Take the survey.

CI/CD 变量故障排除

列出所有变量

你可以使用 Bash 中的 export 命令或 PowerShell 中的 dir env: 命令列出脚本可用的所有变量。这会暴露所有可用变量的值,这可能带来安全风险屏蔽变量 显示为 [MASKED]

例如,使用 Bash:

job_name:
  script:
    - export

示例作业日志输出(已截断):

export CI_JOB_ID="50"
export CI_COMMIT_SHA="1ecfd275763eff1d6b4844ea3168962458c9f27a"
export CI_COMMIT_SHORT_SHA="1ecfd275"
export CI_COMMIT_REF_NAME="main"
export CI_REPOSITORY_URL="https://gitlab-ci-token:[MASKED]@example.com/gitlab-org/gitlab.git"
export CI_COMMIT_TAG="1.0.0"
export CI_JOB_NAME="spec:other"
export CI_JOB_STAGE="test"
export CI_JOB_MANUAL="true"
export CI_JOB_TRIGGERED="true"
export CI_JOB_TOKEN="[MASKED]"
export CI_PIPELINE_ID="1000"
export CI_PIPELINE_IID="10"
export CI_PAGES_DOMAIN="gitlab.io"
export CI_PAGES_URL="https://gitlab-org.gitlab.io/gitlab"
export CI_PROJECT_ID="34"
export CI_PROJECT_DIR="/builds/gitlab-org/gitlab"
export CI_PROJECT_NAME="gitlab"
export CI_PROJECT_TITLE="GitLab"
...

启用调试日志

调试日志可能带来严重的安全风险。输出包含作业可用的所有变量内容。输出会上传到 GitLab 服务器并在作业日志中可见。

你可以使用调试日志来帮助排查流水线配置或作业脚本的问题。调试日志会暴露通常由 runner 隐藏的作业执行细节,并使作业日志更加详细。它还会暴露作业可用的所有变量和密钥。

在启用调试日志之前,请确保只有团队成员可以查看作业日志。在重新公开日志之前,你还应该删除包含调试输出的作业日志

要启用调试日志,将 CI_DEBUG_TRACE 变量设置为 true

job_name:
  variables:
    CI_DEBUG_TRACE: "true"

示例输出(已截断):

...
export CI_SERVER_TLS_CA_FILE="/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE"
if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
  echo $'
'\x1b[32;1mFetching changes...\x1b[0;m'
'
  $'
'cd'
' "/builds/gitlab-examples/ci-debug-trace"
  $'
'git'
' "config" "fetch.recurseSubmodules" "false"
  $'
'rm'
' "-f" ".git/index.lock"
  $'
'git'
' "clean" "-ffdx"
  $'
'git'
' "reset" "--hard"
  $'
'git'
' "remote" "set-url" "origin" "https://gitlab-ci-token:[email protected]/gitlab-examples/ci-debug-trace.git"
  $'
'git'
' "fetch" "origin" "--prune" "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/lds"
++ CI_BUILDS_DIR=/builds
++ export CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace
++ CI_PROJECT_DIR=/builds/gitlab-examples/ci-debug-trace
++ export CI_CONCURRENT_ID=87
++ CI_CONCURRENT_ID=87
++ export CI_CONCURRENT_PROJECT_ID=0
++ CI_CONCURRENT_PROJECT_ID=0
++ export CI_SERVER=yes
++ CI_SERVER=yes
++ mkdir -p /builds/gitlab-examples/ci-debug-trace.tmp
++ echo -n '-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----'
++ export CI_SERVER_TLS_CA_FILE=/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE
++ CI_SERVER_TLS_CA_FILE=/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE
++ export CI_PIPELINE_ID=52666
++ CI_PIPELINE_ID=52666
++ export CI_PIPELINE_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/pipelines/52666
++ CI_PIPELINE_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/pipelines/52666
++ export CI_JOB_ID=7046507
++ CI_JOB_ID=7046507
++ export CI_JOB_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/-/jobs/379424655
++ CI_JOB_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/-/jobs/379424655
++ export CI_JOB_TOKEN=[MASKED]
++ CI_JOB_TOKEN=[MASKED]
++ export CI_REGISTRY_USER=gitlab-ci-token
++ CI_REGISTRY_USER=gitlab-ci-token
++ export CI_REGISTRY_PASSWORD=[MASKED]
++ CI_REGISTRY_PASSWORD=[MASKED]
++ export CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/gitlab-examples/ci-debug-trace.git
++ CI_REPOSITORY_URL=https://gitlab-ci-token:[MASKED]@gitlab.com/gitlab-examples/ci-debug-trace.git
++ export CI_JOB_NAME=debug_trace
++ CI_JOB_NAME=debug_trace
++ export CI_JOB_STAGE=test
++ CI_JOB_STAGE=test
++ export CI_NODE_TOTAL=1
++ CI_NODE_TOTAL=1
++ export CI=true
++ CI=true
++ export GITLAB_CI=true
++ GITLAB_CI=true
++ export CI_SERVER_URL=https://gitlab.com:3000
++ CI_SERVER_URL=https://gitlab.com:3000
++ export CI_SERVER_HOST=gitlab.com
++ CI_SERVER_HOST=gitlab.com
++ export CI_SERVER_PORT=3000
++ CI_SERVER_PORT=3000
++ export CI_SERVER_SHELL_SSH_HOST=gitlab.com
++ CI_SERVER_SHELL_SSH_HOST=gitlab.com
++ export CI_SERVER_SHELL_SSH_PORT=22
++ CI_SERVER_SHELL_SSH_PORT=22
++ export CI_SERVER_PROTOCOL=https
++ CI_SERVER_PROTOCOL=https
++ export CI_SERVER_NAME=GitLab
++ CI_SERVER_NAME=GitLab
++ export GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,wip_limits,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
++ GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,wip_limits,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
++ export CI_PROJECT_ID=17893
++ CI_PROJECT_ID=17893
++ export CI_PROJECT_NAME=ci-debug-trace
++ CI_PROJECT_NAME=ci-debug-trace
...

调试日志的访问权限

调试日志的访问权限仅限于至少拥有 Developer 角色的用户。当通过以下方式启用调试日志时,角色较低的用户无法查看日志:

如果你将 CI_DEBUG_TRACE 作为本地变量添加到 runners,调试日志会生成并且对所有有权访问作业日志的用户可见。runner 不会检查权限级别,因此你应该只在 GitLab 本身中使用该变量。

argument list too long 错误

当为作业定义的所有 CI/CD 变量的总长度超过作业执行的 shell 所施加的限制时,就会出现此问题。这包括预定义变量和用户定义变量的名称和值。此限制通常称为 ARG_MAX,并且取决于 shell 和操作系统。当单个文件类型变量的内容超过 ARG_MAX 时,也会出现此问题。

有关更多信息,请参见问题 392406

作为解决方法,你可以:

  • 尽可能使用文件类型 CI/CD 变量来处理大型环境变量。
  • 如果单个大型变量大于 ARG_MAX,请尝试使用安全文件,或通过其他机制将文件带到作业中。

下游流水线的 Insufficient permissions to set pipeline variables 错误

触发下游流水线时,你可能会意外收到此错误:

失败 - (无法创建下游流水线,设置流水线变量的权限不足)

当下游项目具有受限的流水线变量且触发作业满足以下任一条件时,会发生此错误:

  • 定义了变量。例如:

    trigger-job:
      variables:
        VAR_FOR_DOWNSTREAM: "test"
      trigger: my-group/my-project
  • 从顶层 variables 部分中定义的默认变量接收变量。例如:

    variables:
      DEFAULT_VAR: "test"
    
    trigger-job:
      trigger: my-group/my-project

传递给下游流水线的触发作业变量是流水线变量,因此解决方法是:

同名作业变量中的默认变量不会展开

你不能在同名的作业变量中使用默认变量的值。只有当作业没有定义同名变量时,默认变量才可用。如果作业有同名变量,则作业变量优先,默认变量在作业中不可用。

例如,这两个示例是等效的:

  • 在此示例中,$MY_VAR 没有值,因为它没有在任何地方定义:

    Job-with-variable:
      variables:
        MY_VAR: $MY_VAR
      script: echo "Value is '$MY_VAR'"
  • 在此示例中,$MY_VAR 没有值,因为同名的默认变量在作业中不可用:

    variables:
      MY_VAR: "Default value"
    
    Job-with-same-name-variable:
      variables:
        MY_VAR: $MY_VAR
      script: echo "Value is '$MY_VAR'"

在这两种情况下,echo 命令都会输出 Value is '$MY_VAR'

通常,你应该直接在作业中使用默认变量,而不是将其值重新赋给新变量。如果需要这样做,请使用不同名称的变量。例如:

variables:
  MY_VAR1: "Default value1"
  MY_VAR2: "Default value2"

overwrite-same-name:
  variables:
    MY_VAR2_FROM_DEFAULTS: $MY_VAR2
  script: echo "Values are '$MY_VAR1' and '$MY_VAR2_FROM_DEFAULTS'"