no_proxy にネットワークアドレスとかワイルドカードを指定しても期待通りに動かない、でどうするかというお話
世の中には、イントラなど直接インターネットに繋ぐことができず、プロキシ経由でしかインターネットに出られない環境で、検証をやっている人も多いと思います。 僕自身もそういうことが多く、検証環境を作り直す度にプロキシ設定不備で無駄にハマったりと時間をとられることが度々ありました。
それで、この際、ちゃんとまとめておくかと思ってブログを書き始めたのですが、ぐぐってみると全く同じような問題意識で書かれたブログ記事があって、全般的な内容はそちらに書かれていたので、落ち穂拾い的に no_proxy の設定だけ補足を書いてみます。
プロキシ設定についての全般的な内容が書かれているブログはこちら。
上記のブログでは、見落としがちで面倒なsudoの設定や、gitの設定まで網羅されているので、大概のプロキシ設定はこの内容で何とかなると思います。*1
ということで、プロキシ設定全般の話は、そちらを参照してもらえばよくなったので、落ち穂拾いとして、こちらには書かれていない no_proxy のハマりどころだけ取り上げたいと思います。
Linuxで、プロキシを設定するのに一番簡単な方法は、以下のように環境変数でプロキシ設定をする方法です。これを設定していると多くのプログラムで、指定されたプロキシを使うようになっています。
export http_proxy=http://proxy.example.com:8080/
export https_proxy=http://proxy.example.com:8080/
ただ、この方法だとそのシェルから実行されるプログラムでのHTTP(S)アクセスがすべてプロキシ経由となってしまうため、検証環境内部で動いているサービスへのアクセスにもプロキシを使おうとしてしまいます。 それを避けるために設定するのが「no_proxy」環境変数です。たとえば、以下のように設定します。
export no_proxy=127.0.0.1,localhost,192.168.1.1
たとえば、ログインシェルからクライアント起動して検証環境内部のコンポーネントに直接HTTP通信を行い、同時に、最新のソースコードやパッケージはプロキシを通じて外部から取得したい場合*2には、このように「no_proxy」まで設定してやる必要があります。
ここまでは上記のブログにも書かれている内容です。
ただ、この際の「no_proxy」の仕様が曲者で、僕が確認したプログラムではここに設定できるのは「IPアドレス」もしくは「ドメイン名」のみとなっており、プロキシを経由したくないIPアドレスを複数指定する場合は、IPアドレスをひたすらカンマ区切りで列挙する必要があります。たとえば、内部サーバへの接続の際にIPアドレスをそのまま使っている場合、プロキシ経由してほしくないIPアドレスのすべてをここに書き下すことになります。 たとえば"192.168.0.0/24"とか"172.16.0.*"といった、ネットワークアドレスでの指定やワイルドカードでの指定は期待通りの動作になりません。
参照サイト
ちなみに、ここの回答で根拠になっているドキュメントは、wgetのmanページの記述のようです。まさに環境変数そのものの仕様を定めたものは見つからず…。環境変数の扱いは、それぞれのアプリケーションが独自に扱いを決めていて、標準仕様はないということかな。*3*4
ちょっとそれましたが、このような仕様のため、参照サイトでは以下のように、一つ前のブログで書いたようなブレース展開をしたカンマ区切りリスト作成でのno_proxy指定が紹介されています。bashをログインシェルにしている環境で、かつ、/etc/environment ではなく、/etc/bashrc 等に書かないと期待した動作にならないと思いますが、参考までに。
printf -v no_proxy '%s,' 10.1.{1..255}.{1..255};
export no_proxy="${no_proxy%,}";
また上記の例ではもう一つ注意点があり、この例のとおりに「no_proxy」を設定すると、環境変数があまりに長くなりすぎて、以下のようなエラーでvimなどが起動できなくなるという問題があります。なので、とにかく使いそうなIPを全部入れるのではなく、必要最低限の範囲で設定しないといけません。以下のようなエラーが出るようになってしまった場合は「unset no_proxy」で、一旦変数を削除したあとに再設定するのが吉です。
$ vim
-bash: /usr/bin/vim: 引数リストが長すぎます
ちなみに、ブレース展開を使った設定では一つ前のブログのもう一つの手法を使って、以下のようにすることもできます。こちらもbashオンリーです。
no_proxy=$(echo 192.168.1.{1..5})
export no_proxy=127.0.0.1,localhost,${no_proxy// /,}
どちらにしても、環境変数に長大なIPリストができてしまうのは避けられませんが、、、
あまりに長くなる場合は、ドメイン名での振り分けを聞くようにするとか、別の方法を考えたほうがよさそうです。
このネタはこんなところで。
*1:こちらのブログでは /etc/environmentでシステムワイドの環境変数を設定していますが、僕自身はこのファイルでの設定に馴染みがないので、/etc/profileや/etc/bashrcでシェル向けに環境変数を設定しています。/etc/profileや/etc/bashrcはシェルスクリプトなので、スクリプトでの処理結果やbash拡張機能を使った出力結果を環境変数に指定することができます。一方、/etc/environmentは、スクリプトではなく、pam_env.soが読み込むデフォルト環境設定ファイルです。
*2:具体的には社内にOpenStack検証環境を作るときとか
*3:たとえば、こんな記事も見つけました。「HTTP::Tiny 0.32で no_proxyがサポートされました」 http://d.hatena.ne.jp/syohex/20130622/1371884244
bashのブレース展開を使ってカンマ区切りリストを作る
bash操作のTipsメモです。
bashには、ブレース展開というブレース({}のカッコのこと)の中身を一定の法則で展開して、半角スペース区切りのリストにしてくれる機能があります。
例えば、以下のように使うことができます。
$ echo 192.168.1.{1,3} 192.168.1.1 192.168.1.3 →ブレースの直前の文字列にカンマで区切った文字列を組み合わせたリストに変換 $ echo 192.168.1.{1..5} 192.168.1.1 192.168.1.2 192.168.1.3 192.168.1.4 192.168.1.5 →数値の連番の場合は ".." で数値を繋ぐとその範囲で数値を変化させたリストに変換 $ echo /opt/{app,db}/{data,conf} /opt/app/data /opt/app/conf /opt/db/data /opt/db/conf →複数のブレースがある場合は、そこに入っている値の組み合わせでのリストを出力。 これによってまとめて複数のディレクトリを作ったりすることができる。
「ブレース展開」でググると、いろいろな使い方が紹介されているのを見つけることができますが、例えば、 http://d.hatena.ne.jp/xr0038/20111221/1324446298 では使い方の具体例がいろいろ紹介されています。
これは非常に便利な機能なのですが、値の区切るデリミタが必ず半角スペースになってしまうので、例えば、カンマ区切りでホスト名が欲しい時*1などは、得られた結果を素朴に sed で置換していました。*2
sedを使った素朴な変換の例
$ hostlist=$(echo 192.168.1.{1..5} | sed 's/ /,/g') $ echo $hostlist 192.168.1.1,192.168.1.2,192.168.1.3,192.168.1.4,192.168.1.5
これ自体は汎用的な方法で、特に問題があるわけではありませんが、せっかくbash組み込みの機能を使っているので、sedを使わないでできる方法を調べてみました。
bash組み込み機能を使うと、以下の方法で半角スペースからカンマへの変換ができます。
bashの変数展開時のパターンマッチを使ったやり方
$ hostlist=$(echo 192.168.1.{1..5}) # ${変数名//パターン/文字列/} とするとパターンに一致するすべての部分を文字列で置換したものを返す $ echo ${hostlist// /,} 192.168.1.1,192.168.1.2,192.168.1.3,192.168.1.4,192.168.1.5
bash組み込みのprintfコマンドを使った方法
# bash組み込みのprintfコマンドは "-v 変数名" でその変数に出力結果を格納することができる $ printf -v hostlist '%s,' 192.168.1.{1..5} # ${変数名%パターン} とすると、変数末尾をパターンマッチし最短マッチ部分を削除された結果を出力する # それを利用して最後の余分なカンマを削除する $ echo ${hostlist%,} 192.168.1.1,192.168.1.2,192.168.1.3,192.168.1.4,192.168.1.5
前者はsedにも近い書式のパターンマッチで比較的覚えやすく、値を使う際にデリミタを切り替えて使えるというメリットがあります。一方、後者は printf が /usr/bin/printf ではなく、bash組み込みコマンドの方になっている*3という罠があるのに加えて、変数展開も独自書式なので、この場合はあまり向いていなさそうです。
bashのパターンマッチには、ここで使った以外にもシェルを使った作業を効率的に勧められるようなものが揃っています。
参考サイト
例としては、パターンマッチと同じ方法を使ったディレクトリ名、ファイル名が挙げられているのをよく見ます。
$ filepath=/path/to/file.txt $ dir=${filepath%/*} # => /path/to $ filename=${filepath##*/} # => file.txt
ただ、僕としてはディレクトリ名、ファイル名の取得では、専用コマンド dirname, basename を使う方がお勧めです。bash依存にならずに済みますし、これらのコマンドはオプションを使うことで、拡張子を除いたファイル名を取り出すといった操作がより直感的にできるからです。
公開されているスクリプトを読んだ時に、この書き方が出てくることがあるので、こういう書き方があるのか、ぐらいに覚えておくのがいいと思います。*4
今日のところは、ここまでで。
シェルスクリプトのコーディングスタイル・コーディング規約について考えてみる
シェルスクリプトのコーディングスタイルについて調べ物をしたので、その情報源の一覧と今の感想のメモを書いてみます。
- 最もよく参照されているのではないかと思われるシェルスクリプトのコーディングスタイル。
上記のページの最初には「ここに書かれている内容は、あくまで筆者の好みでありほぼ完全に主観」と書かれていますが、この内容は規約としてどこでも採用すべき内容だと思います。また定数には大文字の変数名を使うというガイドラインですが、自分で書く場合、環境変数も大文字変数に加えます。
好みがあるとすれば、インデントの幅ぐらいでしょうか?
ここではインデント幅は半角スペース2つが推奨されていますが、個人的には半角スペース4の方が好みです。
Pythonのコーディング規約PEP 8を見ても、タブとスペースを混ぜるな、スペースの方が人気があるので推奨というぐらいの書き方で、明確にインデント幅を指定していないので、インデント幅まではスタイルに含めないのがいいんでしょうか。
Tabs or Spaces? Never mix tabs and spaces. The most popular way of indenting Python is with spaces only.
ちなみに、Pythonライブラリではインデント幅は「4」が多いらしく、僕もPythonのインデント幅は4。シェルスクリプトのインデント幅もそれに合わせているという面が強いです。
以下は、参考になりそうな海外の情報(英語)です。
- SIGNAL Trapを使ったロックファイル削除などについても書いてあるコーディングスタイル。
シグナルを使った終了処理はこういう感じがよさそうです。bashの擬似シグナルは便利だけど、広く使うスタイルとしては入れない方がいいかなと思います。
- 網羅的だけど、かなり長い。。。
- PDF。SIGNAL Trapを使った一次ファイルの削除方法やテスト手法にも言及しているコーディング規約のドキュメント。
以下は、近年のIT勉強会クラスタの議論から。
また、反応としてはだいぶ遅いですが、上に紹介した情報の中の @masudaK さんの「シェルスクリプトを書く際に気を付けていること8箇条」の補足を書いたに若干コメントしたいと思います。
- スクリプトのオプション指定について
上記のエントリに、以下の2つを比較して、前者の方がコードが減るのでベターというコメントがありましたが、僕としては後者の書き方を使っています。
#!/bin/sh -ue
#!/bin/sh set -ue
というのも、以下のようにスクリプトを実行した場合、
sh test.sh
前者は、/bin/sh 、後者は/bin/sh -ue でコマンドが実行され、後者の方が自分の直感に近いからです。
例えば、スクリプトのデバッグのために、一時的に-xオプションを付けてコマンド実行する場合、以下のように実行することが度々あると思うのですが、その際にば前者は、/bin/sh -x 、後者は/bin/sh -xue となってしまい、混乱を招くように思います。*1
sh -x test.sh
なので、スクリプトのオプションはsetコマンドで別の行にて定義するのがいいのかなと。Perlで言うと「use strict; use warnings;」みたいな感じで「set -ue」。*2
上記のエントリではShebangでの「#!/bin/sh」と「#!/bin/bash」で違いがあるのか、という話も出てきますが、それについては別のエントリに書いています。結論からいうと、多くの場合で問題になりませんが、微妙に動作が異なります。
今のところの結論として、最初に紹介しているページの内容に加えて「set -ue」、必要に応じてSIGNAL Trapの使い方を共通認識とするのがいいのかなと思っています。
とはいえ、スタイルや規約には一長一短あるので、このエントリを見てくれた方もリンク先を見て自分に馴染むところを取り入れてもらうのがいいかなと思っておりますです。
「メイド喫茶愛好家の集い」は、秋葉原文化の歴史的転換点(になるはず)
最近、「エヴァンジェリスト」と言われると「メイド喫茶エヴァンジェリスト」のことを指すようになってきた気がしてならないせちろーです。
さて今日、2013年5月11日はメイド喫茶クラスタにとって、非常に重要なイベントの日でした。
その名も「メイド喫茶愛好家の集い」。
この10年の秋葉原のメイド喫茶を引っ張ってきた伝説的なメイド4名が一同に介する史上初のイベントです。募集当日、数時間で席が埋まってしまうほどの人気イベントでしたが、募集直後に見つけることができたため、僕は運良く参加することができました。
- 出演メイドのみなさん
- シャッツキステの有井エリス(@arii_erice)さん
- 元メイリッシュのありさ(@arisa_arisa)さん
- ぴなふぉあの田川まゆみ(@tagawasan)さん
- @ほぉ~むカフェのhitomi(@jjhitomin)さん
このメンバーがどのぐらいすごいのかは、メイド喫茶クラスタ以外には伝わりにくいところがあるのですが、あえてほかの言い方をすれば日本の主要なベンチャー企業トップが一同に会した、とでも言ったらいいでしょうか。メイドさんを3次元の存在にたとえてしまうと大事なことが抜けおちてしまうような気もしますが…。*1
実際に@ほぉ~むカフェのhitomiさんはメイドから@ほぉ~むカフェを運営するインフィニアの取締役社長になり、現役メイドでもありながら競争の激しい秋葉原で5店舗を経営する経営者でもあります。*2
今回のイベントは緩い感じのタイトルとは裏腹に、そういった伝説的メイドの方々と参加者とが、これからのメイド喫茶、これからの秋葉原、そして、それらの文化をこれからどのように育て、どのように世界に発信していくかをテーマに語り合うというガチイベントでした。綺麗な言い方をすると、ボトムアップ型での街づくりを考えるイベントですね。
主宰のたかとらさん(@takatora)、やんさん(@skd7)はすごく真面目で人望のある方で、準備も周到。参加者は事前に自己紹介文を書き、当日、会場で名札と参加者リストが配られるという徹底ぶりです。
そもそもメイド喫茶がなかったころ、「萌え」というフレーズが今のように使われなかったころから、メイドを始め、新たな道を切り開いてきたみなさんのお話はいずれも聴き応えがあり、しかも、これまでのメイドとしての心遣いも感じられるすごくいい話が多かったです。話のスケールも自分の店がどうこうではなくて「世界に対して〜」「30年続けて文化をつくる」ぐらいの視野の話です。
また、参加者も一緒に文化を作り上げる仲間*3として、これまでにメイド喫茶に来たことがない人に、様々なテーマ・コンセプトのメイド喫茶があることを伝え、お店に来やすい雰囲気を作っていくのかを真剣に考えていました。
こういう感じのかなり本気なイベントではありましたが、やはりメイド喫茶愛好家の集いということとで、最後は「萌え萌えじゃんけん」の生みの親であるhitomiさんの指導のもと、ありささんとみんなで萌え萌えじゃんけんをやるという完璧な締め(笑)
写真はとれなかったので、司会だったササキチさん(@sasakichi_akiba)さんのつぶやきを拝借します。リンク先のブログから麗しい伝説のメイドの姿をご覧ください。
記者の方も入っていたので、詳細な記事が出るのを期待して待っています(・∀・)
30年後の日本史の教科書にはこのイベントが秋葉原文化の歴史的転換点として載るようになり、プロジェクトXばりののドキュメンタリーとしてまとめられる日が来るのを妄想する次第です。
お店に興味があって行ってみたい方がいれば、もちろん僕もご一緒させてもらいますので声かけてくださいまし。
ーーーー
5/12 7:38 追記
ほかの方の報告ブログやエリスさんの脳内スチルなどです。
「hbstudy #44 ベンチマーク勉強会(基礎編) 現場で役立つベンチマークのススメ」に行ってきた。
こんにちは。
最近、どんなブログを書いても「どんまいこの花嫁修業」には勝てない気がしているせちろーです。とはいえ、最近まじめにやっていない勉強会参加報告ブログを書いてみたいと思います。
さて、5月10日は「hbstudy #44 ベンチマーク勉強会(基礎編) 現場で役立つベンチマークのススメ」が新宿でありました。*1講師は、日本国内では数少ない(らしい)職業的ベンチマーカーの宮原さん@tmiyahar。
内容は、宮原さんがベンチマークの裏話や機材、ベンチマーク手法について、ニヤニヤしながら楽しそうに2時間半語り倒すという非常にマニア向けな内容です。(笑)
ですが、そんな内容に惹かれて集まった参加登録者は開催時点で122人。スタッフも入れたら、当日は130人はいたんじゃないでしょうか。
これだけの人数が集まったのは、ベンチマークはインフラエンジニアの基礎技術の一つだと思いますが、一般的な確立された手法がなく、ベンチマークの第一人者である宮原さんが話す内容に注目が集まったからだと思います。かく言う、僕もベンチマークの度に試行錯誤している身です。
勉強会の資料はこちらにアップされているので、内容全般はそれを見てみてください。ベンチマークの基本的な考え方、ハマりどころ、具体的な手法が網羅された非常に良い資料なので、エンジニア必読の資料だと思います。また、今回はベンチマーク勉強会とも共同開催となっていましたので、ベンチマーク勉強会の資料も一緒にアップされています。
http://connpass.com/event/2366/?disp_content=presentation#tabs
会場では、資料には載せられないような裏話もちらほらありましたが、それが聞けるのは直接会場にいた人の特権ということでご容赦くださいませ。
宮原さんの発表で特に気になったポイントは、勉強会中に他の人のTweetのRTも含めてつぶやいていますが、以下のようなところです。「ベンチマークは科学!」って辺りは熱いですねw*2
ベンチマークに当たっての基礎的な考え方については、自分でもHPC勉強会*3で10分程度発表したことがありまして、宮原さんの発表はその問題意識にがっちりハマって、実践的なヒントをたくさんもらうことができました。ちなみに、当時の自分の発表資料は以下になります。
コンピュータシステムの特性や性能を正確に把握するというのは、非常に基本的なことではありますが、実際にやるためには対象への理解とその理解に即した測定を行うスキルの両方が必要で、かつ、技術面以外でもいろいろなバイアスがかかりやすい非常に難しいことだと思います。それを乗り越えて誰もが納得できる客観的な結果を出そうとするという姿勢が「科学」ということでしょう。
今回の勉強会は基礎編ともある通り、基本的な考え方や代表的な手法の紹介の内容だったので、次のベンチマーク勉強会では実践編として何かのベンチマークのハンズオンをやりたいという話が上がっています。ベンチマーク対象に取り上げるものがまだ決まっていませんが、自分としても開催に協力して実現したいと思っていますので、興味がある方は是非!
今日はこんなところで。
Fabric で fabfile.py のコメントを使ったタスクの簡易Usage
最近、Fabric関連のエントリが流行っているようなので、ネタかぶりしない範囲で小ネタをちょっと書いて見ます。
Fabricは、単純にタスクを実行するだけはなく、実行するタスクに引数を渡すことができます。
以下は引数の渡し方についてのPython製デプロイツール Fabricを初めて使う際に役立つTipsからの引用です。
タスクに引数を渡したい場合がありますよね。 解決策 $ fab hoge:fuga でhoge関数の第一引数に’fuga’を渡すことができます。 $ fab hello:name=Jeff とかね。 最初に提示したチュートリアル(Overview and Tutorial)に載っているから詳しくはそっち参考にしてね。
この引数指定機能は非常に便利なのですが、時間が経つと各タスクにどういう引数があったのか忘れてしまい、都度ソースを確認してしまうことがしばしば…。
それでなんとかできないかと思っていたのですが、あるときにタスクにコメントを書いてみたところ、これが fab --list の出力結果に表示される機能があることを発見。この機能を使うと fab --list で表示できる簡易マニュアルを書くことができます。
そこにタスクの引数を書いておけば、簡易Usage機能のように使えます。
具体的にはこんな感じ。*1
def deploy_vmwaretools(): """ fab deploy_vmwaretools:host=192.168.1.1 """ archive_name = 'VMwareTools-9.0.0-782409.tar.gz' put(archive_name, '/tmp') (いろいろ作業) def initial_setting(type='ubuntu12.04'): """ fab initial_setting:host=192.168.1.1,type=ubuntu12.04 """ set_vim() (いろいろ作業)
$ fab --list Available commands: deploy_vmwaretools fab deploy_vmwaretools:host=192.168.1.1 initial_setting fab initial_setting:host=192.168.1.1,type=ubuntu12.04 restart (以下略)
ほかにもコメントの使い方はありそうですが、これで僕のような忘れっぽい人は少し幸せになれると思います。
*1: host, hostsは特別な引数で host=host1、hosts="host1;host2" のような形式で実行対象ホストを指定することができます。
Zabbix向けのHadoopメトリクス取得用スクリプトとテンプレート
先週からZabbix向けのHadoopメトリクス取得用スクリプトとテンプレートをこっそり公開していました。
プログラムとしてはかなり荒削りな状態なので、これまでGithubに上げただけにしていましたが、それだけではあまり意味が無いので、今さらブログで取り上げてみる次第です。
URLは以下。
今上がっているものは、HadoopとHBaseのメトリクスを取得する外部チェックスクリプトとZabbixテンプレート生成スクリプト、生成済みテンプレートのセットです。
監視の観点では、しきい値の設定やグラフの設定など、まだ追加しないといけない要素があるのですが、まずは基本のところのみ上げています。
こちらはすべて /jmx のJMXサーブレットのインターフェースを使用します。
/metrics のメトリクスサーブレットを使うスクリプトもアップしていますが、これは参考扱いで。
これらのインターフェースの違いについては、以下を参照してください。
まずはアップしてある監視テンプレートをZabbixサーバにインポートして、どのようなアイテムが登録されているのか見てもらえると取れるメトリクスの雰囲気がつかめるのではないかなと思います。
普段ごりごりプログラムを書いている人から見ると、スクリプトには変なところも多々あると思いますが、その際はお手柔らかにご指導いただけると嬉しいです。
また、HBaseの情報取得は試験中としていますが、これは 0.94 になってメトリクスが非常に増えていて、その扱いが判断しきれていないことが主な理由です。今アップしているテンプレートは、手元の環境で取れたメトリクスすべてから生成していますが、その状態だとRegionserver向けの監視アイテムだけで722個。情報の取捨選択は悩ましいところです…。
これはちゃんと精査して、環境に合わせたテンプレート生成を行わないとなかなか実用にならないと思いますが、今のところは使う方が必要、不要をより分けていただければと思います。