宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
1つ前のエントリで、Rubyでバッククォートで実行した外部コマンドの標準出力を何故か受け取れないと書いてたんだけど、追記した通り、これは「RubyスクリプトがCGIで実行されているせいで標準入出力がCGI用に使われており、バッククォートで起動した子プロセスはその標準入出力を引き継ぐから、子プロセスから標準出力に出した内容が文字列として呼び出し元のスクリプトに返される代わりに、CGI経由でクライアント(GitHubのService Hookのエージェント)に返されてしまっている」ということだった(すとうさんに教えていただいた)。
で、対策として spawn()
と Process.waitpid()
を使うと良いというアドバイスを頂いて、以下のように直してみた。
#!/usr/bin/ruby1.9.1
require "cgi"
require "shellwords"
require "json"
require "logger"
require "stringio"
SYNC_SCRIPT = "/home/piro/shared/or/tools/upload_nightly_xpi.sh"
RELEASE_SCRIPT = "/home/piro/shared/or/tools/release_addon.sh"
SSH_KEY = "/path/to/secret_key"
BASE_DIR = "/home/piro/shared/xul"
USER = "piro"
logger = Logger.new("/home/piro/shared/post-receiver.log")
#logger = Logger.new("/dev/null")
logger.level = Logger::INFO
# 子プロセスの実行結果(標準出力)を常に文字列で受け取るユーティリティ
def run(command_line)
pipe_in, pipe_out = IO.pipe
Process.waitpid(spawn(command_line, [:out, :err] => pipe_out))
pipe_out.close
pipe_in.read
end
cgi = CGI::new
puts "Content-Type: text/plain\n\n"
begin
payload, = cgi.params["payload"]
payload = JSON.parse(payload)
project = payload["repository"]["name"]
project_dir = File.join(BASE_DIR, Shellwords.escape(project))
makefile = File.join(project_dir, "Makefile")
if File.exist?(project_dir) and File.exist?(makefile)
logger.info "build #{project}"
sudo = "sudo -u #{USER} -H"
command_line = "#{sudo} #{SYNC_SCRIPT} -i #{SSH_KEY} -b #{BASE_DIR} -d #{project_dir}"
logger.info command_line
logger.info run(command_line)
command_line = "cd #{project_dir}; git describe"
logger.info command_line
current_commit = run(command_line).strip
logger.info current_commit
# 現在のコミットがタグを打ったまさにそのコミットである場合、
# git describeの結果はタグ名だけになる。
# なので、それをトリガーにしてリリース処理を走らせる。
if !current_commit.empty? && !current_commit.match(/\A.+-[0-9]+-g[0-9a-f]+\z/)
logger.info "=> release commit"
command_line = "#{sudo} #{RELEASE_SCRIPT} -i #{SSH_KEY} -b #{BASE_DIR} -n #{project}"
logger.info run(command_line)
else
logger.info "=> regular commit"
end
end
logger.info "ok"
p "ok"
rescue Exception => error
logger.error error
logger.info "ng"
p "ng"
end
run()
というのを定義していて、ここでパイプを作って spawn()
の子プロセスの標準入出力に設定して、実行が終わるまで待ってパイプから実行結果を文字列として読み出す、ということをしている。(パイプを使う方法もすとうさんに教えていただいた。)
あと、このスクリプトは ~/public_html 以下に置いてるんだけど、apacheユーザで実行されてしまってファイルのアクセス権が……という事にも地味に悩まされていて、それでsudoを使ってたんだけど、suexecというApacheモジュールを使うと良いと教えてもらって sudo a2enmod suexec; sudo service apache2 restart としてみた。でもこの状態で git pull とかさせるとどういうわけか「error: cannot open .git/FETCH_HEAD: Permission denied」と言われてしまって(whoの結果ではapacheユーザじゃなくpublic_htmlがあるユーザになってるのに、何故だ……)、それで結局相変わらずsudoしている。
の末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2013-04-02_autobuild.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。
writeback message: Ready to post a comment.