LoginSignup
0
0

More than 5 years have passed since last update.

Chef Push-Jobsを利用して、任意コマンドのリモート実行&出力の取得

Posted at

目的

Push-Jobsを利用すると、ワークステーション環境から、事前定義したコマンドの実行をnodeに指示できます。
Push-Jobsの基本的な説明は以下をご参照ください。
https://docs.chef.io/push_jobs.html

Push-Jobsを利用したところ、個人的に以下2点が課題になりました。

・ジョブの事前定義が必要で、任意のコマンドを実行できない
・nodeでジョブ実行した際の出力を確認できない
("output"オプションで出力を取得できる仕様ですが、現時点ではSJISの2バイト文字が含まれると取得できなかったり、取得できる出力のサイズ上限が固定であったりします。)

そこで、カスタマイズを行い課題を解消します。

構成

Chef Server 12.17.15
Push Jobs Server 2.2.8
Chef Client 13.4.24
Push Jobs Client 2.5.6
node Platform : AIX7, RHEL7, Windows2016

手順

1. Chef Server nginxのconfファイルを追加

/var/opt/opscode/nginx/etc/nginx.d/export.conf

server {
    listen 60080;
    root /tmp/push-jobs;
    location = /log {
        client_max_body_size 1m;
        client_body_buffer_size 1m;
        content_by_lua_block {
            ngx.req.read_body()  -- explicitly read the req body
            local data = ngx.req.get_body_data()
            if (not data) then
                ngx.say("no body in request.")
                return
            end
            local file = string.match(data, 'filename="(.+)"')
            if (not file) then
                ngx.say("no filename in request body.")
                return
            end
            local logdir = "/tmp/push-jobs/log"
            local status, err = pcall(os.execute, "mkdir -p "..logdir)
            local filepath = logdir.."/"..file
            local f, err = io.open(filepath, "w")
            if err then
                ngx.say("can not open file on chef server: ", filepath)
                return
            end
            f:write(data)
            f:close()
            ngx.say("output data to file on chef server: ", filepath)
        }
    }
}

nginxを再起動

chef-server-ctl restart nginx

2. nodeのwhiteにコマンドを登録

AIX,Linux

        "script-exec-simple": "chmod 755 ${CHEF_PUSH_JOB_FILE} && ${CHEF_PUSH_JOB_FILE} ${CHEF_PUSH_JOB_ID} ${CHEF_PUSH_NODE_NAME}",

Windows

        "script-exec-simple": "powershell -Command \"mv %CHEF_PUSH_JOB_FILE% %CHEF_PUSH_JOB_FILE%.PS1; %CHEF_PUSH_JOB_FILE%.PS1 %CHEF_PUSH_JOB_ID% %CHEF_PUSH_NODE_NAME% \"",

3. Chefサーバに以下のディレクトリ・ファイルを作成

ディレクトリ作成
/tmp/push-jobs/log/
/tmp/push-jobs/script/

ファイル作成
/tmp/push-jobs/script/tmplate-lin

jobId=$1
nodeName=$2
logfile=/tmp/${jobId}-${nodeName}.log

cd /tmp
curl -O -k http://ChefServer:60080/script/tmpCommand
curl -O -k http://ChefServer:60080/script/http_file_upload.rb
chmod 755 tmpCommand http_file_upload.rb

LANG=C echo "#logfile head" > $logfile
LANG=C /tmp/tmpCommand  >> $logfile 2>&1
RC=$?
LANG=C echo '#logfile end' >> $logfile
echo RC=${RC} >> $logfile

ruby /tmp/http_file_upload.rb $logfile

/tmp/push-jobs/script/tmplate-win

Param( $jobId, $nodeName )
$logfile="C:/tmp/${jobId}-${nodeName}.log"
$httpUploadRb="C:/tmp/http_file_upload.rb"

Set-Location "C:/tmp/"
Invoke-WebRequest http://ChefServer:60080/script/tmpCommand -OutFile tmpCommand.ps1
Invoke-WebRequest http://ChefServer:60080/script/http_file_upload.rb -OutFile http_file_upload.rb
echo "#logfile head" | Out-File ${logfile} -Encoding UTF8
.tmpCommand.ps1 2>&1 | Out-File ${logfile} -Encoding UTF8 -Append
${RC}=$LastExitCode
echo '#logfile end' | Out-File ${logfile} -Encoding UTF8 -Append
echo "RC=${RC}" | Out-File ${logfile} -Encoding UTF8 -Append
C:/opscode/chef/embedded/bin/ruby C:/tmp/http_file_upload.rb ${logfile}

/tmp/push-jobs/script/http_file_upload.rb

require 'net/http'
require 'uri'
require 'base64'

uri = URI.parse('http://ChefServer:60080/log')
sendString = Base64.urlsafe_encode64(open(ARGV[0]).read)
sendFileName = File.basename(ARGV[0])
data = [[ "upfile", sendString, { filename: sendFileName, content_type: "application/octet-stream" } ]]

http = Net::HTTP.new(uri.host, uri.port)
req = Net::HTTP::Post.new(uri.path)

req.set_form(data, "multipart/form-data")
res = http.request(req)

puts res.code
puts res.msg
puts res.body

/tmp/push-jobs/script/file_decode.rb

require 'base64'
puts Base64.urlsafe_decode64(open(ARGV[0]).read)

以上で準備完了です。

4. 実行してみます。

まず、実行したいコマンドを以下のファイルに記載します。

/tmp/push-jobs/script/tmpCommand

以下のようにジョブを実行します。

knife job start script-exec-simple <node name> --file /tmp/push-jobs/script/tmplate-lin

ジョブ終了後、以下のファイルがChefサーバに作成されているはずです。

/tmp/push-jobs/log/<jobId>-<nodeName>.log

取得したファイルから必要な個所を抜き出し、base64でデコードすれば、出力を確認できます。

grep "I2xvZ2ZpbGUgaGVhZA" /tmp/push-jobs/log/<jobId>-<nodeName>.log | sed -z 's/\r\n//g' > /tmp/push-jobs/log/<jobId>-<nodeName>.log
ruby /tmp/push-jobs/script/file_decode.rb /tmp/push-jobs/log/<jobId>-<nodeName>.log

※I2xvZ2ZpbGUgaGVhZAは"#logfile head"をencodeした文字列です。

感想

こんなことするなら、シンプルにSSH/winrm 使いますよね。。。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0