JenkinsのSlaveノードの冗長化を考えてみた

f:id:suganoo:20181015183735p:plain
Jenkinsを構築しているんですが、障害対策を検討してみたお話です。

自分ところで使ってるJenkinsはそれほどクリティカルではないにせよ、Jenkinsのノードが落ちてしまったりするとリカバリがなかなか大変なので障害対策をしておきたかったわけです。

Masterに関しては、Docker上で動かしてイメージをエクスポートしてバックアップしておき復旧をお手軽にしておいた。

そんでSlave側ノード、つまり接続先が何かしらで応答しなくなった時どうしよっか?と考えて、対処tipsを書いておこうと思いました

何をしたいのか

  • 設定が全く同じSlaveノードを2台用意してある。(slave01, slave02とする)
  • 通常はslave01を使う。
  • 接続先のSlave01ノードが落ちてた場合、すぐに別の冗長化したSlave02ノードに接続してジョブを実行してもらいたい。

f:id:suganoo:20181015170343p:plain

これを考えた時、LBで振り分けるか、DNSで死活監視してIPを書きかえるか、を考えたけどめんどくさくなりそうなのでやめた。

  • LBで振り分ける
    • 書いてなかったけど、Jenkinsはaws EC2上でSlaveはオンプレ。ELB使おうと思ったけど、ELBはオンプレのIPを振り分けられない。
    • ALBとかほかのサービスとか、LBサーバー建てるかとか、考えたけど管理するものを増やしたくなかったのでボツ。
  • DNSで振り分ける
    • 監視して振り分けようかと思ったけど、これもそこまでDNS使う必要あるか?と思ってやめた。
    • また、監視スクリプトとかもDNSに紐づいてると、こちらも管理が増えそうだったのでやりたくなかった。

ちなみにだけどプラグインでそういうことができるものがあるか調べたのだけど、どうもやりたいことを実現できそうなプラグインが見つからなかった。

どうやって解決したか

プロジェクトの設定にある「実行するノードを制限」のラベル式を使ったのと、Jenkinsのapiを使ってノードをオンライン/オフラインで切り替えてみた。

ラベル式

プロジェクト設定の「実行するノードを制限」のラベル式を使ってみた。
f:id:suganoo:20181015181952p:plain
このラベル式はなかなか曲者で、これ使えば意図通りにできるんじゃないの!?っと淡い期待をした。
けども、いろいろ試した結果ラベル式はよくわからなかった。。。。

けども試したところ、|| (ラベルのOR条件)は使えそうとわかったのでOR条件を使うことにした。

ラベル式に(!hoge)とかhoge && fuga とか指定できるけど、正直振る舞いがよくわからない。
良くおできになるエンジニアの方は頑張って調査してみてほしいです。

ちなみに

ちなみに||でつなぐとこうなりました。

実行するノードを確認のため、ジョブで実行するシェルスクリプトにhostnameを実行し実行ノードを確認しています。

実行するノードのラベル式 実行ノード
slave01 || slave02 slave02
slave02 || slave01 slave02
hoge || slave02 || slave01 slave02

なぜslave02が優先されるのかはわからなかった。
名前順なのか?、接続レスポンスが短い順?かと思ったけどそうでもなさそう。わからんーー!

ですが、ノードのオフライン条件を加えると意図通りになった。

ラベル式 slave01の状態 slave02の状態 実行ノード
slave01 || slave02 online offline slave01
slave01 || slave02 offline online slave02

これを使おうというわけです。

Slaveのオンライン/オフラインの切り替え

探してみたところ切り替え用のapiがあるようです。ラッキー!!

下記のようにcurlを実行するとSlaveノードのオンライン/オフラインが切り替えられる。

curl -s -XPOST --user (user):(apitokenxxxx) 'http://localhost:8080/computer/slave02/toggleOffline'

APIトークンですが、jenkinsの画面の右上にある「ユーザー→設定」で下記のようにAPIトークンが取得できます。
f:id:suganoo:20181015181906p:plain
APIトークンは一回しか表示されないから注意!

またオフラインの状態確認は下記のcurlで取得できます。

curl -s -XGET --user (user):(apitokenxxxx) 'http://localhost:8080/computer/slave02/api/json?pretty=true'

結果は省略しますが、こんな感じの結果が取得できます。

{
  "_class": "hudson.slaves.SlaveComputer",
  "actions": [],
  "assignedLabels": [
    {
      "name": "slave02"
    }
........
  "offline": false,
........

この"offline"キーで状態が取れるので、それをもとにしてオンライン/オフラインを切り替えることにした。
"offline":falseオンライン状態
"offline":true オフライン状態
(間違えそうだー)

ちなみにですが、"temporarilyOffline"というのもあります。
これはノード設定の画面から「このノードを一時的にオフラインにする」を押すと"temporarilyOffline":trueになる。

例えばなにかしらの理由でslave01が使えなくなった時を想定して、slave01のremote.jarプロセスを全部killしてみると、"offline":trueだけど"temporarilyOffline":falseになります。
なので"offline"で判断したほうがよさげ。

ジョブの設定と監視

ジョブの設定

ジョブ側の設定については「実行するノードを制限」のラベル式を「slave01 || slave02」にするだけです。

監視側

  • 定常状態をslave01:オンライン、slave02:オフラインにしておきます。
  • apiで取得できる"offline"キーを定期的に監視します。
  • slave01がオフラインになってたらslave02をオンラインに復活させます。

これでジョブをなるべく止めることなく動かすようにしてみた。

監視のスクリプトは省略。

最後に

良く調べたらtoggleOfflineだけじゃなくてdoDisconnectやlaunchSlaveAgentもあるみたいですね。
stackoverflow.com


状態にかかわらず一方的にオフライン/オンラインできるならこれの方がいいかも。


オンライン/オフラインって言葉間違えてないかな,.......

【プログラミング】codewarsがすんごくいい教材だった

f:id:suganoo:20181010185308p:plain


twitterでフォローしてる @yuki_sato さんから(勝手に)知ったのですが、とてもいいプログラミング学習サイトを知りました。

codewars
https://www.codewars.com

どんな人使うといいの?

ざっくりいうと、初級者競プロのプログラミングの課題サイトって感じでしょうか。

progateなどのようにプログラミングを0から学ぶスタイルではありません。

すでにある程度、なんとかググりながらコーディングできるレベル、の人が使うといいでしょう。

対応言語がいっぱいある!

驚いたのですが、学べる言語がかなり豊富です。

Java, ruby, python, などの言語は対応してるんですが、Haskell, F, F#, solidity...まで対応してるんですよ!
(問題数にかたよりはあると思いますが。。)

自分はjavascriptを学びたいのでjavascriptやってます。

回答するとベストプラクティスが出る

またもう一ついいことに、課題を解くとベストプラクティスが出るんですね。
これは学ぶ上でかなり助かります。

例えばこれ

  • ある数値が与えられる。その数値を2進数で表す時の1の数を返しなさい。
  • ex. 5 → "101" → 2、 7 → "111" → 3

自分が書いたコードはこれです。

var countBits = function(n) {
  // Program Me
  var num_one = 0;
  while ( 0 < n ) {
    if ( n % 2 == 1 ) {
      num_one++;
    }
    n = Math.floor( n / 2 );
  }
  return num_one;
};

ですが、ベストプラクティスだとなんと1行でできます。

countBits = n => n.toString(2).split('0').join('').length;

おおーすごい!

最後

こういうベストプラクティスが出るのはありがたいですわ。

知らなけらばどうしてたってわからないですもん。


コツコツやってみようと思います。

【beeline】Required field 'client_protocol' is unset!

beelineでHadoopにつなごうとしたらこんなエラーがでて困った。

18/10/10 15:59:41 [main]: ERROR jdbc.HiveConnection: Error opening session
org.apache.thrift.TApplicationException: Required field 'client_protocol' is unset! Struct:TOpenSessionReq(client_protocol:null, configuration:{use:database=default, set:hiveconf:hive.server2.thrift.resultset.default.fetch.size=1000})

その時の解決方法。

条件とやりたいこと

やりたいこと

  • すでにHadoopクラスターができている。
  • そのクラスターに対して新しいノードからクライアントしてbeelineを使いたかった。

条件など

  • Hadoopはclouderaを使っている。
  • エラーが出た時、Hiveはapache hive からダウンロードして使っていた。

ちなみにhive 1.2.2も2.3.3も3.1.0も使ってみたが、どのバージョンも同じようなエラーだった。

解決方法

cloudera からHiveをインストールする!

stackoverflowなどをみて解決方法を探ってたら
「hive-jdbc-1.2...だとかバージョン落としてみたら」とか
「metasrore_dbの場所が違うんじゃ?」とか出てきたけど
全然関係なかった。

cloudera のHiveを使えば解決しました。

sudo su -

# OSのバージョンは適宜変更してね
wget http://archive.cloudera.com/cdh5/redhat/7/x86_64/cdh/cloudera-cdh5.repo


# clouderaのバージョンが異なるのであれば変えておくこと。
vi cloudera-cdh5.repo

# ex.
# -------------------------------------------------------
baseurl=https://archive.cloudera.com/cdh5/redhat/7/x86_64/cdh/5/
↓
baseurl=https://archive.cloudera.com/cdh5/redhat/7/x86_64/cdh/5.15.0/
# -------------------------------------------------------

mv cloudera-cdh5.repo /etc/yum.repos.d/

yum install hive

これでうまくいった。

依存関係でhadoopコマンドやhdfsコマンドもインストールされるのね。

「HTMLとCSSで基礎から学ぶJavaScript」を読んでみた

HTMLとCSSで基礎から学ぶJavaScript

HTMLとCSSで基礎から学ぶJavaScript

しばらく前に読んだので更新しておく。

Javascriptを学びたくて買ってみました。

感想としてはうーん...という感じ。


初心者向けの本なのですが、説明が多くて文章がいっぱいあり読むのがつらくなってしまいました。

内容も古くなっており、中古だったからしょうがないんですけどね、最近のHTML5などには対応してなさそう。


もっとほかにいい本があるだろう。

「いちばんよくわかるHTML5&CSS3デザインきちんと入門」を読んでみた

いちばんよくわかるHTML5&CSS3デザインきちんと入門 (Design&IDEA)

いちばんよくわかるHTML5&CSS3デザインきちんと入門 (Design&IDEA)

こんな本を読んでみました。

仕事では使わないのですが、やっぱりWebサービスを作ってみたいなという熱が出てきました。
そこでamazonを物色したりフロントエンド関連のブログを探したところ、これに行きつきました。

感想としては、かなりいい本でした。

仕事柄フロントエンドの知識ってネットに頼るしかないんですよね。
ですが、この本を読むことで体系的なHTML、CSSの知識がついてかなり満足です。

パンくずリスト、flex-boxのやり方、divやspanの使い方など
あーこうやって作るんだー!と理解できるところが多くてよかったです。


自分がWebサイトを作るとしたら不得意なCSSとかにはエネルギーを使わず、bootstrapみたいなツールを使うと思います。
ですが、それがどうやって表現されているのか?に理解があるとちょっとした修正がしやすくなったり、設計がへんてこりんにならなかったりするメリットがあると思います。

うーんかなりいい本でした。


(こっちの本もよかったです)
suganoo.hatenablog.com

【Solidity】CryptoZombiesはブロックチェーンの勉強にむちゃくちゃいい教材だ!【Blockchain】

f:id:suganoo:20181001171524p:plain
cryptozombies.io

ここしばらく昼休みにちょこちょこCryptoZombiesをやってたのですが、すごくいい教材でした。

何が学べるのか

ざっとピックアップしてみますが、こんな感じでした。

  • Solidity contractの書き方
  • 各種関数修飾子の使い方
  • ゲームアプリケーションでの使い方
  • ERC721規格について
  • オーバーフロー、アンダーフローの対策
  • フロントエンドからweb3.jsの使い方

などなど。
Ethereum, Solidityの知識が身に付きます。

正直課題をこなしてるだけになり意味の理解が手薄になってしまい、上に書いた以上のこともあったかもしれません。
ですがかなり内容は網羅されていると思います。

話し言葉が楽しかった

どうでもいいところなのですが、説明するときの話し言葉がなかなか楽しいんですよね。

レッスン 2までよくぞたどり着いた!

このレッスン 2では、人間に噛み付いてゾンビ軍団を倍増させる方法を教えてやるが、怖がらずにしっかり学ぶのだ。

なんかこう、よくあるRPG的にプログラミングを学ばす感じでね。

各国言語にやくされてるみたいなので、どなたか日本語版をがんばったんだなーとよくわかります。

学ぶのが楽しくなります!

感想

アプリケーションとして使うための基礎的な知識が学べたのではと思います。
実践的にHTML, javascriptを含めてweb3.js, solidityが学べるのはほんとによかったです。

正直後半1/3くらいからややこしくなってきて、こなしてるだけになってしまいました。
なので今は復習してます。

これをやるとフロントエンドの知識ないのですが、がぜんやる気になってしまいました。

レッスンは今のところ(2018/10/01現在)6レッスンまでで、今後増える様子です。
アップデートが楽しみだなあ。

CryptoZombies blockchainを学ぶにはほんとおすすめです。

この本もおすすめ!

ブロックチェーンアプリケーション開発の教科書

ブロックチェーンアプリケーション開発の教科書

【メモ】sshd_configの修正は気をつけろ!最悪ログインできなくなる。

またアホなことやっちまった。。。

sshd_configをいじってたら、ログインできなくなっちまいました。

誰かが同じ轍をふまないように、自分のアホ操作をさらしておきます。

はぁー、EC2インスタンスだったし、デプロイもすぐできるようにしてたのがせめてもの救いでした。


sshd_configの修正はログインできなくなることもあるから気をつけろ!!!

前提条件

自分とこの環境はEC2をコンソールなどでつくるのではなく、それに接続したクラウドサービス経由でインスタンス作ってます。
そのサービスの中で独自にスクリプトを書くことができ、公開鍵まで配置してくれるようにしています。
自分のユーザーは管理者が作っててやたらめったら変更などできません。

なのでどんなインスタンスを作っても、自分の秘密鍵でローカルPCからすぐにsshログインできるようになっています。

はい、もう一回言います。

公開鍵認証でローカルPCからsshログインしていました。パスワードは設定していません。

なにをしたかったのか?

EC2のインスタンスを建てて、特定のユーザー(hogeユーザー)でdocker コンテナや別のインスタンスからログインできるようにしたかったわけです。
パスワード認証で。

インスタンスは作りなおすこともあるので公開鍵認証にしてると再度公開鍵の配置が煩わしいと思ったのでパスワード認証にしてました。

修正方法は?

※実際にコピペして有効にするなよ!やるときはちゃんと考えろよ!

パスワード認証にするには/etc/ssh/sshd_configに下記を書いて有効にします。

PasswordAuthentication yes

書いたらsshdをリロードして反映させましょう。

systemctl reload sshd

修正したらどうなった?

はい、これで別インスタンスからhogeユーザーとしてパスワード認証でsshログインできてめでたしめでたし!
っと思ってログアウトしてみました。


再度ローカルPCからログインしてみると、なんとパスワードを聞かれてログインできない!
最初のログインユーザーではパスワード設定してないので、なんにも対処のしようがありません。\(^o^)/オワタ

まとめ

しかたないのでインスタンスを作り直してどうにかしました。
EC2インスタンスだったこと、まだ中身にはなんも入れてなかったことがせめてもの救いでした。

  • sshd_configの修正はほんとに気を付けよう。
  • ansibleでもシェルスクリプトでも、さっとデプロイできる(復旧できる)操作を作っておいたほうがいいよ。

【Solidity】msg.senderってなに?

solidityを勉強してると、実行を自分のオーナー(?)に限定にするためにこんな書き方をすることがあります。

require(msg.sender == owner)

このmsg.senderは自分で定義してるわけではないので、最初のうちは

どっからこれは来てるんだ???

と戸惑います。


調べてみるとわかりました。
グローバルネームスペースですでに定義されてるやつだったんですね。

同じような質問がstackoverflowにありました。
stackoverflow.com

solidityのドキュメントに書いてあります。ほかにもいろいろありますね。

Units and Globally Available Variables — Solidity 0.4.26 documentation

Block and Transaction Properties

  • block.blockhash(uint blockNumber) returns (bytes32): hash of the given block - only works for 256 most recent, excluding current, blocks - deprecated in version 0.4.22 and replaced by blockhash(uint blockNumber).
  • block.coinbase (address payable): current block miner’s address
  • block.difficulty (uint): current block difficulty
  • block.gaslimit (uint): current block gaslimit
  • block.number (uint): current block number
  • block.timestamp (uint): current block timestamp as seconds since unix epoch
  • gasleft() returns (uint256): remaining gas
  • msg.data (bytes): complete calldata
  • msg.gas (uint): remaining gas - deprecated in version 0.4.21 and to be replaced by gasleft()
  • msg.sender (address payable): sender of the message (current call)
  • msg.sig (bytes4): first four bytes of the calldata (i.e. function identifier)
  • msg.value (uint): number of wei sent with the message
  • now (uint): current block timestamp (alias for block.timestamp)
  • tx.gasprice (uint): gas price of the transaction
  • tx.origin (address payable): sender of the transaction (full call chain)

【Blockchain】【Ethereum】【メモ】Ethereumの情報メモ

※随時更新予定(たぶん。。。)

Ethereumホワイトペーパー

ここのリポジトリを漁ればだいたいのものは入手できそう。
github.com

Tutorial

CryptoZombie

わかりやすい。けっこう楽しい。
cryptozombies.io

【Golang】userパッケージを使ってみる

userパッケージを使ってみました。

user - The Go Programming Language

package main

import (
        "fmt"
        "os/user"
)

func main() {
        user, err := user.Current()
        if err != nil {
                panic(err)
        }
        fmt.Println("User.Name : " + user.Name)
        fmt.Println("User.Uid : " + user.Uid)
        fmt.Println("User.Gid : " + user.Gid)
        fmt.Println("User.Username : " + user.Username)
        fmt.Println("User.HomeDir : " + user.HomeDir)
}
User.Name :
User.Uid : 501
User.Gid : 503
User.Username : hoge
User.HomeDir : /home/hoge

ドキュメントにあるようにUser.Nameはブランクのようです。

【シェルスクリプト】visudoでスクリプトから/etc/sudoersを編集する。

あるユーザー(foobar)ユーザーを作ったからsudo権限をつけたい。
それをスクリプトから実行したい。

としたとき、どうすればいいか?

ちょっと悩みました。

/etc/sudoersは直接編集できないし。。。
visudo でなにかしらのインプットはできない感じだし。

そしたら素晴らしい解法がstackoverflowに投稿されていました。

stackoverflow.com

echo 'foobar ALL=(ALL:ALL) ALL' | sudo EDITOR='tee -a' visudo

天才かよっ!


無事解決できました。

【Golang】runtimeを調べてみた

Go言語のruntimeはOSやプロセスの情報を得ることができます。
runtime - The Go Programming Language


CPU情報はDeprecatedになってしまったようですね。

下記のサンプルコードをもとにちょっと自分でも書いてみました。
golangcode.com

package main

import (
        "runtime"
        "fmt"
        "time"
)

func main() {
        fmt.Println("--- Params ---")
        fmt.Printf("GOROOT = %v\n",runtime.GOROOT())
        fmt.Printf("NumCPU = %v\n",  runtime.NumCPU())
        fmt.Printf("NumGoroutine = %v\n",  runtime.NumGoroutine())

        fmt.Println("--- memory test ---")
        fmt.Println("--- before ---")
        PrintMemUsage()
        fmt.Println("--- start ---")
        var mem_alloc [][]int
        for i := 0 ; i < 4 ; i++ {
                a := make([]int, 0, 999999)
                mem_alloc = append(mem_alloc, a)

                PrintMemUsage()
                time.Sleep(time.Second)
        }
        PrintMemUsage()
        fmt.Println("--- After GC ---")
        runtime.GC()
        PrintMemUsage()

}

func PrintMemUsage() {
        var m runtime.MemStats
        runtime.ReadMemStats(&m)

        fmt.Printf("Alloc = %v MiB\t", bToMb(m.Alloc))
        fmt.Printf("TotalAlloc = %v MiB\t", bToMb(m.TotalAlloc))
        fmt.Printf("Sys = %v MiB\t", bToMb(m.Sys))
        fmt.Printf("Mallocs = %v MiB\t", bToMb(m.Mallocs))
        fmt.Printf("Frees = %v MiB\t", bToMb(m.Frees))
        fmt.Printf("HeapAlloc = %v MiB\t", bToMb(m.HeapAlloc))
        fmt.Printf("HeapSys = %v MiB\t", bToMb(m.HeapSys))
        fmt.Printf("NumGC = %v", m.NumGC)
        fmt.Printf("\n")
}

func bToMb(b uint64) uint64 {
        return b / 1024 / 1024
}

こんな結果が取れます。

--- Params ---
GOROOT = /opt/go
NumCPU = 1
NumGoroutine = 1
--- memory test ---
--- before ---
Alloc = 0 MiB   TotalAlloc = 0 MiB      Sys = 1 MiB     Mallocs = 0 MiB Frees = 0 MiB   HeapAlloc = 0 MiB       HeapSys = 0 MiB NumGC = 0
--- start ---
Alloc = 7 MiB   TotalAlloc = 7 MiB      Sys = 11 MiB    Mallocs = 0 MiB Frees = 0 MiB   HeapAlloc = 7 MiB       HeapSys = 8 MiB NumGC = 1
Alloc = 15 MiB  TotalAlloc = 15 MiB     Sys = 19 MiB    Mallocs = 0 MiB Frees = 0 MiB   HeapAlloc = 15 MiB      HeapSys = 16 MiB        NumGC = 2
Alloc = 22 MiB  TotalAlloc = 22 MiB     Sys = 26 MiB    Mallocs = 0 MiB Frees = 0 MiB   HeapAlloc = 22 MiB      HeapSys = 23 MiB        NumGC = 3
Alloc = 30 MiB  TotalAlloc = 30 MiB     Sys = 34 MiB    Mallocs = 0 MiB Frees = 0 MiB   HeapAlloc = 30 MiB      HeapSys = 31 MiB        NumGC = 4
Alloc = 30 MiB  TotalAlloc = 30 MiB     Sys = 34 MiB    Mallocs = 0 MiB Frees = 0 MiB   HeapAlloc = 30 MiB      HeapSys = 31 MiB        NumGC = 4
--- After GC ---
Alloc = 0 MiB   TotalAlloc = 30 MiB     Sys = 34 MiB    Mallocs = 0 MiB Frees = 0 MiB   HeapAlloc = 0 MiB       HeapSys = 31 MiB        NumGC = 5

【Ansible】ansible-playbookのオプション調べてみた

f:id:suganoo:20180904182719p:plain
ちょっと自分のメモがてらansbileのオプションを書き留めておきます。

それぞれのファイルの正式な書き方や説明は省略します。

よく使う実行コマンド

ansibleコマンド

ansible-playbook prod.yml -i ./hosts -c paramiko --vault-password-file=pass/vault_password_file --diff

設定ファイルなど

playbookファイル
- name: インストール 本番環境
  hosts: hosts_prod
  serial: 1
  user: hoge
  become: true
  vars_files:
    - group_vars/common_params.yml
  roles:
    - role: install_common
      tags: cmn
    - role: install_aws
      tags: aws
hostsファイル
[hosts_prod]
prod_01
prod_02
[hosts_dev]
dev_01

オプション

-i INVENTORY

インベントリを指定します。これが指定されることにより、playbook中でhosts: hosts_prodと指定することができます。

-k, --ask-pass

ログイン時にパスワードを要求します。

-c CONNECTION

コネクションタイプ。 -k でログインする際は、-c paramikoを指定しないとエラーになる。理由は不明。

--vault-password-file

ansible-vault で暗号化したファイルのパスワードファイル

--diff

デプロイ時に差分表示

-v

デプロイ詳細を表示。-vvv, -vvvv でさらにもっと詳細表示。

--check -C

差分確認だけでデプロイしない。

--step

1ステップごと確認しながらデプロイする。

--tags

playbookに書いたタグを指定して実行する。

--skip-tags

タグ指定したもの以外を実行する。


なぜプログラミングを学ぶならUdemyがおすすめなのか!?

確認用オプション

下記のオプションは調べてて知りました。便利だなぁ。

--list-hosts

デプロイするホストを表示する。

ansible-playbook prod.yml -i hosts --list-hosts
playbook: prod.yml

  play #1 (hosts_prod): インストール 本番環境       TAGS: []
    pattern: [u'hosts_prod']
    hosts (2):
      prod_02
      prod_01

--list-tags

ロールのタグを表示する。

ansible-playbook prod.yml -i hosts --list-tags
playbook: prod.yml

  play #1 (hosts_prod): インストール 本番環境       TAGS: []
      TASK TAGS: [cmn, aws]

--list-tasks

ロールのタスクを表示する。

ansible-playbook prod.yml -i hosts --list-tasks
playbook: prod.yml

  play #1 (hosts_prod): インストール 本番環境       TAGS: []
    tasks:
      install_common : create git clone dir {{ git_clone_dir }}  TAGS: [cmn]
      install_common : create log org dir {{ log_org_dir }}        TAGS: [cmn]
(省略)

まとめ

--help を使えば他にも出てきます。
--list-* のオプションは今回記事を書かなかったら知らなかったなあ。
いつか使ってみよう。

Ansibleの書籍は一冊買っておくとなにかと便利ですよ。

Ansible実践ガイド 第2版 (impress top gear)

Ansible実践ガイド 第2版 (impress top gear)

【PR】搾取されてない.....!?
客先常駐で働いているエンジニアの方お疲れ様です。
IT業界でSESとして働いている人は多いんですが、自分のマージンや月額単価を知らない人がけっこう多いみたいですね。
自分もそうでした。(^^;)
でもそれかなりもったいないですよ。理由はこちらリツアンSTCの紹介記事を見てみてください。
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
blog.suganoo.net

【Golang】tmpファイルを扱う

f:id:suganoo:20180904093850p:plain
Golangにはtempとしてのファイル操作関数があるんですね。便利ですね。
あまり使う用途ないかもしれませんが、パッと見関数で何やってるかわかって可読性がちょっとよくなるかもしれません。

サンプルコード

package main

import (
        "io/ioutil"
        "os"
        "log"
        "fmt"
)

func main() {
        temp_file, err := ioutil.TempFile(os.TempDir(), "tempfile-test-")
        if err != nil {
                fmt.Println("Error, can not create temp file.")
                log.Fatal(err)
        }

        fmt.Println("File : " + temp_file.Name())

        _, err = temp_file.Write([]byte("This is temp file.\n"))
        if err != nil {
                fmt.Println("Error, can not write on temp file.")
                log.Fatal(err)
        }

        //defer os.Remove(temp_file.Name())
}
File : /tmp/tempfile-test-158369842

ポイント

ioutil.TempFile

https://golang.org/pkg/io/ioutil/#TempFile

func TempFile(dir, pattern string) (f *os.File, err error)

dir ディレクトリに、patternから始まるランダムの数値を付加したファイルを作ります。
patterntempfile-test-としてたのでtempfile-test-158369842となりました。

ioutil.TempDir

https://golang.org/pkg/io/ioutil/#TempDir

func TempDir(dir, prefix string) (name string, err error)

ちなみにTempDirはtempディレクトリを作ります。

os.TempDir

https://golang.org/pkg/os/#TempDir

func TempDir() string

基本的に$TMPDIRを返すか、無ければ/tmpを返します。

まとめ

Temp関係の関数があるのは便利かも。
でもどこで使おうか。知ってて損はないかな。

pythonでもそういう機能あるんだね。
pythonで一時ファイル、一時ディレクトリ(tempfile)