这个问题是在新装 gitlab-ce 到 Ubuntu 14.04 上发生的。报错如下:

# gitlab-ctl reconfigure
Starting Chef Client, version 12.12.15
resolving cookbooks for run list: ["gitlab"]
Synchronizing Cookbooks:
 - package (0.0.0)
 - runit (0.14.2)
 - gitlab (0.0.1)
Installing Cookbook Gems:
Compiling Cookbooks...
Recipe: gitlab::default
 * directory[/etc/gitlab] action create (up to date)
init (upstart 1.12.1)
 Converging 288 resources
 * directory[/etc/gitlab] action create (up to date)
 * directory[Create /var/opt/gitlab] action create (up to date)
 * directory[/opt/gitlab/embedded/etc] action create (up to date)
 * template[/opt/gitlab/embedded/etc/gitconfig] action create (up to date)
Recipe: gitlab::web-server
 * group[Webserver user and group] action create (up to date)
 * user[Webserver user and group] action create (up to date)
Recipe: gitlab::users
 * directory[/var/opt/gitlab] action create (up to date)
 * group[GitLab user and group] action create (up to date)
 * user[GitLab user and group] action create (up to date)
 * template[/var/opt/gitlab/.gitconfig] action create (up to date)
Recipe: gitlab::gitlab-shell
 * ruby_block[directory resource: /var/opt/gitlab/git-data] action run

================================================================================
 Error executing action `run` on resource 'ruby_block[directory resource: /var/opt/gitlab/git-data]'
 ================================================================================

Mixlib::ShellOut::ShellCommandFailed
 ------------------------------------
 Failed expecting "/var/opt/gitlab/git-data" to be a directory.
 ---- Begin output of set -x && [ -d "/var/opt/gitlab/git-data" ] ----
 STDOUT:
 STDERR: sh: 1: Bad substitution
 ---- End output of set -x && [ -d "/var/opt/gitlab/git-data" ] ----
 Ran set -x && [ -d "/var/opt/gitlab/git-data" ] returned 2

Cookbook Trace:
 ---------------
 /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/storage_directory_helper.rb:124:in `validate_command'
 /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/storage_directory_helper.rb:112:in `block in validate'
 /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/storage_directory_helper.rb:111:in `each_index'
 /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/storage_directory_helper.rb:111:in `validate'
 /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/libraries/storage_directory_helper.rb:87:in `validate!'
 /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/definitions/storage_directory.rb:35:in `block (3 levels) in from_file'

Resource Declaration:
 ---------------------
 # In /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/definitions/storage_directory.rb

26: ruby_block "directory resource: #{params[:path]}" do
 27: block do
 28: # Ensure the directory exists
 29: storage_helper.ensure_directory_exists(params[:path])
 30:
 31: # Ensure the permissions are set
 32: storage_helper.ensure_permissions_set(params[:path])
 33:
 34: # Error out if we have not achieved the target permissions
 35: storage_helper.validate!(params[:path])
 36: end
 37: not_if { storage_helper.validate(params[:path]) }
 38: end
 39: end

Compiled Resource:
 ------------------
 # Declared in /opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/definitions/storage_directory.rb:26:in `block in from_file'

ruby_block("directory resource: /var/opt/gitlab/git-data") do
 params {:path=>"/var/opt/gitlab/git-data", :owner=>"git", :group=>nil, :mode=>"0700", :name=>"/var/opt/gitlab/git-data"}
 action [:run]
 retries 0
 retry_delay 2
 default_guard_interpreter :default
 block_name "directory resource: /var/opt/gitlab/git-data"
 declared_type :ruby_block
 cookbook_name "gitlab"
 recipe_name "gitlab-shell"
 block #<Proc:0x000000044f0980@/opt/gitlab/embedded/cookbooks/cache/cookbooks/gitlab/definitions/storage_directory.rb:27>
 not_if { #code block }
 end

Platform:
 ---------
 x86_64-linux


Running handlers:
Running handlers complete
Chef Client failed. 0 resources updated in 03 seconds

按照

等等的说法,并不能解决问题。

不得不进入跟踪和研究。

然后发现

Mixlib::ShellOut::ShellCommandFailed
 ------------------------------------
 Failed expecting "/var/opt/gitlab/git-data" to be a directory.
 ---- Begin output of set -x && [ -d "/var/opt/gitlab/git-data" ] ----
 STDOUT:
 STDERR: sh: 1: Bad substitution
 ---- End output of set -x && [ -d "/var/opt/gitlab/git-data" ] ----
 Ran set -x && [ -d "/var/opt/gitlab/git-data" ] returned 2

其实已经提示了足够的信息,期间的弯路略过不提;我需要强调的是,根据源码来看,启动一个shell process是没有问题也无法调整的。

对于上述错误来讲,原因现在已经很明了了:

shell脚本片段“

set -x && [ -d "/var/opt/gitlab/git-data" ]

” 在正常情况下应该根据目录的存在性和可访问性返回0或1,分别代表true和false状态。

然而, “[]” 测试语句是只有 bash/zsh 之类的新式 Shell 才支持的测试表达式,而 Ubuntu 14.04 的默认 Shell(/bin/sh)是指向 /bin/dash,而dash对这样的表达式的应答正是“Bad Substitution”。

由于 gitlab-ctl reconfigure 在安装配置过程中会更新 cookbooks 组件的源码到最新状态,所以唯一可行的办法是换掉Ubuntu的默认Shell:

mv /bin/sh{,.1}

ln /bin/bash /bin/sh

接下来,gitlab-ctl reconfigure 顺利完成。