envsubstで簡易テンプレートを実現する
設定ファイルとかで一部だけ可変にしたテンプレートを使いたいんだけど、RubyとかPerlみたいな別言語を使うまでも無くシェルスクリプトだけで完結したい場合、envsubstコマンドを使うとテンプレートに環境変数を埋め込むことが出来ます。
インストール (on Ubuntu)
% docker run -it --rm ubuntu:16.04 root@a70695314424:/# apt-get update root@a70695314424:/# apt-get install gettext-base -y root@a70695314424:/# envsubst --version envsubst (GNU gettext-runtime) 0.19.7 Copyright (C) 2003-2007 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Bruno Haible.
使い方
root@a70695314424:/# envsubst --help Usage: envsubst [OPTION] [SHELL-FORMAT] Substitutes the values of environment variables. Operation mode: -v, --variables output the variables occurring in SHELL-FORMAT Informative output: -h, --help display this help and exit -V, --version output version information and exit In normal operation mode, standard input is copied to standard output, with references to environment variables of the form $VARIABLE or ${VARIABLE} being replaced with the corresponding values. If a SHELL-FORMAT is given, only those environment variables that are referenced in SHELL-FORMAT are substituted; otherwise all environment variables references occurring in standard input are substituted. When --variables is used, standard input is ignored, and the output consists of the environment variables that are referenced in SHELL-FORMAT, one per line. Report bugs to <bug-gnu-gettext@gnu.org>.
標準入力が標準出力にアウトプットされます。標準入力中の $VARIABLE
もしくは ${VARIABLE}
が実際の環境変数に置換されます。
root@a70695314424:/# echo 'pwd=${PWD}' > sample.tpl root@a70695314424:/# envsubst < sample.tpl pwd=/
基本的にはファイルに書き込んで使います
root@a70695314424:/# envsubst < sample.tpl > sample.txt root@a70695314424:/# cat sample.txt pwd=/
SHELL-FORMAT
が指定されてる場合、そこに書かれている変数だけが使われます、デフォルトは全環境変数が利用可能
root@a70695314424:/# echo 'pwd=${PWD} home=${HOME}' > sample.tpl root@a70695314424:/# envsubst '$HOME' < sample.tpl pwd=${PWD} home=/root
--variables
が指定されてる場合、標準入力は無視されて SHELL-FORMAT
で指定されている変数名が出力されます (値ではない)。
root@a70695314424:/# envsubst --variables '$HOME $PWD FOO' HOME PWD
クラスインスタンス変数はそのクラスからしか参照できない
RubyのクラスはClassクラスのオブジェクトなので、インスタンス変数を持てます。クラスレベルとかクラスメソッドの中で定義された@付きの変数はクラスインスタンス変数(Class Instance Variable)と呼ばれ、そのクラスからしか参照できません、継承されてる場合、継承先でも参照できません。仕事中に継承しているクラスでBaseの値を参照しようとしてちょっとハマった次第であります。
バージョンは2.5.0です。
class Base def self.get @keys end def self.add(key) @keys ||= [] @keys << key end add("Base") end class A1 < Base add("A1-1") add("A1-2") end class A2 < A1 add("A2") end class B1 < Base add("B1") end class B2 < B1 add("B2") end puts "Base=#{Base.get}" puts "A1=#{A1.get}" puts "A2=#{A2.get}" puts "B1=#{B1.get}" puts "B2=#{B2.get}"
出力はこんな感じになります。
Base=["Base"] A1=["A1-1", "A1-2"] A2=["A2"] B1=["B1"] B2=["B2"]
なので、継承ツリー上にある全部の @keys
の値が欲しい場合、全部で get
をしてやる必要があります。
p A2.ancestors.select{|k| k <= Base}.inject([]){|sum, k| sum + k.get} => ["A2", "A1-1", "A1-2", "Base"]
JenkinsでJobを起動して、終了まで待つシェルスクリプト
jqとcurlがインストールされている必要があります。Jenkinsのバージョンは 2.46.3
で認証を有効にしています。
#!/bin/bash # # Trigger a Jenkins build and wait for the build to finish. # set -eu JENKINS_HOST="jenkins.kamatama41.com" JENKINS_USER=kamatama41 JENKINS_TOKEN=xxxxxxxxxx JENKINS_JOB="a-jenkins-job" BODY=$(cat << EOS {"parameter": [ {"name":"FOO", "value":"BAR"} ]} EOS ) get_build_status() { local build_number=$1 curl -sS --fail \ --user ${JENKINS_USER}:${JENKINS_TOKEN} \ https://${JENKINS_HOST}/job/${JENKINS_JOB}/${build_number}/api/json } echo "Start to build ${JENKINS_JOB} with ${BODY}" last_build_id=$(get_build_status lastBuild | jq -r .id) echo "Last build_id is #${last_build_id}" # Trigger the Job curl -sS --fail -X POST \ --user ${JENKINS_USER}:${JENKINS_TOKEN} \ --data-urlencode json="${BODY}" \ https://${JENKINS_HOST}/job/${JENKINS_JOB}/build # Wait for new build to start build_id=$(get_build_status lastBuild | jq -r .id) wait_seconds=3 while [ "${build_id}" == "${last_build_id}" ]; do echo "New build is not running yet, wait for ${wait_seconds} seconds..." sleep ${wait_seconds} build_id=$(get_build_status lastBuild | jq -r .id) done echo "A new build has been started." echo "https://${JENKINS_HOST}/job/${JENKINS_JOB}/${build_id}/" # Wait for the build to end result=$(get_build_status ${build_id} | jq -r .result) wait_seconds=30 while [ "${result}" == "null" ]; do echo "Build is not finished yet, wait for ${wait_seconds} seconds..." sleep ${wait_seconds} result=$(get_build_status ${build_id} | jq -r .result) done if [ "${result}" != "SUCCESS" ]; then echo "Not succeeded, result is ${result}." exit 1 else echo "Succeeded!" fi
解説
/job/${JOB_NAME}/${BUILD_ID}/api/json
でビルドのステータスをJSONで取得出来ます。lastBuild
をIDに指定すると、最後に実施された(or 実施中の)ビルド状態を取得できます/job/${JOB_NAME}/build
にPOSTすると、新しいビルドをトリガー出来ます、JSONでビルドパラメタを渡すことも可能です。 トリガーされたビルドは開始されるまで数秒のタイムラグがあるので、最初にlastBuildのidを取得しておき、ポーリングして番号が変わったらそれが今回起動されたビルドだと判断しています。*1- その後はビルドステータスをポーリングし、
result
がnullで無くなったらビルド完了と判断します。
*1:並列にバンバンビルドが起動されている環境だとこのやり方は誤検知の可能性があります。厳密にチェックする方法も無くはないのですが、面倒なので今回のケースではこういう方法を選びました。
xargsとddcpで高速にファイルをコピーする
総量350GBくらいの大量にファイルが入ってるディレクトリをコピーしないといけなくなったので、xargsとddcpを使って頑張ってコピーした時の記録
- もっと簡単に出来る
- もっといい方法がある
ご指摘お待ちしております!
#!/bin/bash SRC_PATH=/foo DST_PATH=/bar PARALLELS=$(nproc) find "${SRC_PATH}" -mindepth 1 -type d -printf "/%P\n" | xargs -P${PARALLELS} -n1 -I {} mkdir -p ${DST_PATH}{} find "${SRC_PATH}" -type f -printf "/%P\n" | xargs -P${PARALLELS} -n1 -I {} /usr/local/bin/ddcp -s ${SRC_PATH}{} -d ${DST_PATH}{}
解説
加地さん引退
発表されてからだいぶ経ってますが*1、ガンバ大阪やジーコジャパンなどで活躍した加地選手が引退しました。
引退会見も"500試合にこだわらない"、"半分以上楽しくなかった"など28歳で代表引退した加地さんらしい引き方かなあと思いました。
加地さんとの思い出
2005年くらいの代表戦でみたのが最初だったと思うのですが、ジーコジャパンでもお荷物扱いで2chでも"ペットボトラー"とか言われてたのが、コンフェデくらいからブラジル戦での幻のゴールもあったり、代表でも不可欠な存在になっていったのがハマるきっかけだったと思います。
このブログでも2006のワールドカップくらいまではかなり言及がありますねw シュバインシュタイガーに削られたときは本気で落ち込みましたよ...
2chの加地スレ影響も大きかったと思います。本当の加地さんの人となりは正直わからないのですがw 加地スレで作られたキャラはすごく良かったです。
とにかく、20年間お疲れ様でした。まだ38歳なので第二の人生楽しんで下さい!
*1:今日気づいた
最近Pythonでハマったことメモ
2年前くらいに書いたAWS Lambda用のPythonスクリプトを修正することになったんですが、環境構築でひたすらハマったのでメモっておきます。
前提
問題1: pip installが上手く行かない
何か pip install xxx
でインストールしようとすると途中で permission denied エラーが出てインストールできません。
例えば pip install awscli
するとこんな感じで /bin/aws
に書き込みをしようとしてエラーになります
IOError: [Errno 1] Operation not permitted: '/bin/aws'
原因としては、いつ追加したか覚えてないんですが、setup.cfgというローカル固有の環境設定をするファイルが追加されてたようで(ref)、これに以下のように書かれてたのが原因でした.
[install] prefix=
Prefix, 自分の環境で言うと /usr/local
がこの設定により打ち消されていたようです、ファイルを消すことで解決。
問題2: Dockerのpythonのコンテナ上でライブラリが読み込めない
pip install xxx
したあとにxxxを使うスクリプトを python foo.py
で実行してもライブラリが読み込めませんでした。
公式の例に書かれてるように --no-cache-dir
を付けることで解決。
pip install --no-cache-dir xxx
問題3: バージョン固定が上手く行かない
requirements.txt を使って使うライブラリを指定してたんですが、2年経ってバージョンが上がってたため、最新用に色々修正しました。その後今のバージョンに固定しておこうかと思ったので、こんな感じで書いたんですが、、
foo==1.2.3 bar==4.5.6
この書き方ローカル開発中のIntelliJで上はちゃんと動いてたんですが、CircleCIで使うDockerの python:2.7
イメージ上で pip install -r requirements.txt
しても上手く必要なライブラリが全部インストールされませんでした。こちらのQiita記事を参考にして、バージョンは constraints.txt
は記述し、 pip install -r requirements.txt -c constraints.txt
とすることで解決。
TOEIC 227回 結果
Listening: 360(365), Reading: 385(330), Total: 745(695) *1
苦節2年でのようやく700点超え。ただListeningはちょっと限界感があるので何かブレイクスルーが必要かも。
過去ログ
- TOEIC 224回 結果 - かまたま日記3
- TOEIC 217回 結果 - かまたま日記3
- TOEIC 213回 結果 - かまたま日記3
- TOEIC 210回 結果 - かまたま日記3
- TOEIC 207回 結果 - かまたま日記3
*1:括弧の中は前回(224回)の得点