読者です 読者をやめる 読者になる 読者になる

ksaitoの日記

日々試したことの覚え書き

gitで過去のコミットを書き換える

gitの最初のcommitにパスワードを書き込んでpushしたとします。さらに、しばらくcommit/pushを繰り返したとします。

下記の手順でパスワードを全てマスクした文字に書き換える事ができますが、cloneして作業している人すべてに影響がでるので作業前には関係者への連絡と準備が必須です。

事前確認

ブランチがクリーンなことを確認します。

$ git status
ブランチ master
nothing to commit, working tree clean
$

下記のようにpasswordが含まれているファイルをを確認します。

$ git grep password
file.txt:password
$

書き換え

filter-branch--tree-filterオプションで各コミットに実行するコマンドを指定します。 確認したfile.txtsedで書き換えます。

$ git filter-branch -f --tree-filter "sed -i -e 's/password/mask/' file.txt" HEAD
Rewrite c5974de297ec5360d0dfce499abccc3073ba0211 (2/2) (0 seconds passed, remaining 0 predicted)
Ref 'refs/heads/master' was rewritten
$

確認

下記の通りpasswordは、消えて…

$ git grep password
$

maskになっています。

$ git grep mask
file.txt:mask
$

以上

pythonの開発環境その2

以前にdirenvとvirtualenvでpythonの開発環境を作る手順を書きました。

ksaito11.hatenablog.com

pythonzを使うとpythonのバージョンも選択できるようになります。

前提パッケージ

ubuntu17.04に下記の前提パッケー時をインストールします。

$ apt-get install -y \
            build-essential \
            zlib1g-dev \
            libbz2-dev \
            libssl-dev \
            libreadline-dev \
            libncurses5-dev \
            libsqlite3-dev \
            libgdbm-dev \
            libdb-dev \
            libexpat-dev \
            libpcap-dev \
            liblzma-dev \
            libpcre3-dev \
            curl \
            python-pip \
            virtualenv

pythonzのインストー

pythonzのREADME.mdの手順をansibleのplaybookにしました。

$ cat python.yml
---
- name: python develop environment
  hosts: all
  tasks:
    - name: pythonzのインストール確認
      stat: path="{{ ansible_user_dir }}/.pythonz/etc/bashrc"
      register: stat
    - name: pythonzのインストール
      shell: curl -kL https://raw.github.com/saghul/pythonz/master/pythonz-install | bash
      when: not stat.stat.exists
    - name: pythonzの設定
      lineinfile:
        dest: "{{ ansible_user_dir }}/.bashrc"
        state: present
        line: "[[ -s $HOME/.pythonz/etc/bashrc ]] && source $HOME/.pythonz/etc/bashrc"
$ ansible-playbook python.yml -c local

pythonのインストー

使いたいバージョンのpythonをインストールします。

$ pythonz install 3.5.0

direnvの設定

direnvの設定は、前回の記事を参照下さい。

direnvに使いたいバージョンを

$ direnv edit .
$ cat .envrc
layout python $(pythonz locate 3.5.0)
$

これで、使いたいバージョンのpythonを利用することが出来ます。

$ cd tmp
direnv: loading .envrc
direnv: export +VIRTUAL_ENV ~PATH
(0)18:31:05 ksaito@dind$ python --version
Python 3.5.0
$

pipのパッケージも環境毎に独立した物になります。

$ pip list --format=columns
Package       Version
------------- -------
appdirs       1.4.3
boto          2.46.1
packaging     16.8
pip           9.0.1
pkg-resources 0.0.0
setuptools    35.0.2
six           1.10.0
wheel         0.29.0
$

プロキシの設定する

プロキシ環境下では、プロキシサーバを設定しないとインターネットに接続できません。 環境変数に設定する場所は、/etc/environment/etc/profile.dだったり、$HOMEの各種シェルの.profileと、いろいろな場所で設定できます。 yumaptといったコマンド毎にも設定場所があり、正しく設定されているか非常に不安になります。

さらに、各種仮想環境やコンテナ環境で、設定場所や反映されるタイミングがいろいろなので整理が必要です。

下記の方針を墨守します。

  • GitにコミットするDockerfileや設定ファイルにプロキシサーバを直書きしない
  • プロキシの設定をシンプルに保ち、(最終的には)ansibleのplay bookにする
  • 一度に沢山考えすぎない…

OS

設定は、/etc/environmentにすることで利用するログインシェルによらず、OS全体で設定できる。

docker build

docker buildでは、--build-arg環境変数を参照して設定する。

makeを使った場合、下記で実行環境に設定されたプロキシ設定を利用できる。

$ grep BUILD_OPTS Makefile
BUILD_OPTS=--build-arg http_proxy=$(shell echo $$http_proxy) --build-arg https_proxy=$(shell echo $$https_proxy) --build-arg no_proxy=$(shell echo $$no_proxy)
        docker build -t $(NAME) $(BUILD_OPTS) .
$ make -nB
docker build -t docker-bp --build-arg http_proxy=http://proxy.co.jp:8080 --build-arg https_proxy=http://proxy.co.jp:8080 --build-arg no_proxy= .
touch build
$

続きは、また今度…

以上

systemdのサービスをansible-playbookのhandlersでうまく記述する方法

ansible-playbookのhandlersでserviceを使ってサービスをリスタート出来ますが、systemdのサービスを再起動しようとしてもエラーになります。

systemdは、設定変更時にsystemctl daemin-reloadを実行してからサービスを再起動する必要があるためです。

下記の例は、systemdで起動するdocker daemonの例です。

handlersに、shellを使ってsystemctl daemin-reloadするハンドラとserviceを使ってリスタートするハンドラを定義します。

notifyで、2つのハンドラを順番に呼び出すことで正しくサービスを再起動してくれます。

tasks:
    - block:
        - name: create docker daemon systemd directory
          file:
            path: "/etc/systemd/system/docker.service.d"
            state: directory
            owner: root
            group: root
            mode: "u=rwx,g=rx,o=rx"
        - name: setup docker daemon proxy
          template:
            src: "{{ item }}.j2"
            dest: "/etc/systemd/system/docker.service.d/{{ item }}"
            owner: root
            group: root
            mode: "u=rw,g=r,o=r"
          notify:
            - daemon reload
            - restart docker
          with_items:
            - 50-http-proxy.conf
      when: http_proxy != ""

  handlers:
    - name: daemon reload
      shell: systemctl daemon-reload
    - name: restart docker
      service: name=docker state=restarted

docker runすると/bin/bash: /bin/bash: cannot execute binary fileが出る場合の対処

コンテナのデバッグで下記のコマンドをよく使います。

$ docker run -it --rm <イメージ> /bin/sh

zabbixのオフシャルイメージの幾つかで下記のようなエラーがでてしばらく悩みました。

$ docker run -it --rm zabbix/zabbix-agent:alpine-3.2-latest /bin/sh
/bin/sh: /bin/sh: cannot execute binary file
$

次のように実行することでエラーを回避出来ます。

$ docker run -it --rm zabbix/zabbix-agent:alpine-3.2-latest -i
bash-4.3#

原因と再現手順

オフシャルイメージのDockerfileを見ると、ENTRYPOINTCMDは、下記のように書かれています。

$ tail -3 Dockerfile
ENTRYPOINT ["/bin/bash"]

CMD ["/run_zabbix_component.sh", "agentd", "none"]
$

5. CMD and ENTRYPOINT better togetherENTRYPOINTCMDを併用することでコンテナ化したバイナリのアプリケーションをENTRYPOINTに指定して、CMDにデフォルトの振る舞いに必要なオプションを指定するというベストプラクティスが紹介されています。

今回のケースでは、ENTRYPOINT/bin/bashが指定されていることで引数に指定した/bin/bashシェルスクリプトと想定して実行しようとしたためにエラーとなりました。

再現してみると下記のようなことが発生していることになります。-iオプションは、bashの対話的な起動オプションでCMDに指定されたシェルを無効にするためのワークアラウンドです。

$ docker run -it --rm zabbix/zabbix-agent:alpine-3.2-latest /bin/bash
/bin/bash: /bin/bash: cannot execute binary file
$ docker run -it --rm zabbix/zabbix-agent:alpine-3.2-latest -i
bash-4.3# /bin/bash /bin/bash
/bin/bash: /bin/bash: cannot execute binary file
bash-4.3#

ENTRYPOINTにシェル以外のバイナリが指定されているコンテナの場合は、下記のような別解で対応します。

$ docker run --entrypoint /bin/sh -it --rm zabbix/zabbix-agent:alpine-3.2-latest
/var/lib/zabbix #

これで、Dockerfileの設定にかかわらず内容を確認できるようになりました。

s3cmd syncでシンボリックリンクのコピー

s3cmd syncで下記のようなシンボリックリンクをコピーすると無限に深いディレクトリを作り続けます。(何れどこかでエラーになると思いますが…)

$ ls -l .fcpcache
lrwxr-xr-x@ 1 user  staff  1  3 11 16:40 .fcpcache -> .
$

Dockerコンテナでdebconfのdialogを使う

Dockerコンテナでdialogを使ってインタラクティブに設定をするための設定です。

コンテナからdebconf実行

特別何もしないとtextで入力を求められます。

sudo docker run -it --rm -e TZ=Asia/Tokyo -e LANG=ja_JP.UTF-8 ubuntu:16.10 bash
root@b1af411dee00:/mnt# dpkg-reconfigure debconf
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)
debconf: falling back to frontend: Readline
Configuring debconf
-------------------

設定に debconf
を用いるパッケージは、共通のルック&フィールを用います。どの種類のユーザインターフェイスを用いるかを選んでください。

「ダイアログ」は全画面の文字ベースのインターフェイスです。「readline」はより伝統的なプレーンテキストのインターフェイスです�
��「gnome」と「kde」は近代的な X のインターフェイスで、それぞれのデスクトップに適しています (ほかの X
環境で利用することもできます)。「エディタ」を用いるとあなたの好きなテキストエディタを用いることができます。「非対話的」�
�選ぶとまったく質問をしなくなります。

  1. ダイアログ  2. Readline  3. Gnome  4. Kde  5. エディタ  6. 非対話的
利用するインターフェイス: 

whiptailをインストールして再実行

whiptailは、newtというテキストベースのウィンドウツールです。

これがないので、利用できるtextが選択されたのですね。

再実行するとおなじみのダイアログが表示されました。

root@b1af411dee00:/mnt# apt-get install whiptail
root@b1af411dee00:/mnt# dpkg-reconfigure debconf
  ┌────────────────────────────────────────────────────────────────────────────┤ Configuring debconf ├────────────────────────────────────────────────────────────────────────────┐  
  │ 設定に debconf                                                                                                                                                                │  
  │ を用いるパッケージは、共通のルック&フィールを用います。どの種類のユーザインターフェイスを用いるかを選んでください<E3>                                                        │  
  │ <80><82>                                                                                                                                                                      │  
  │                                                                                                                                                                               │  
  │ 「ダイアログ」は全画面の文字ベースのインターフェイスです。「readline」はより伝統的なプレーンテキストのインターフェイ<E3><82>                                                  │  
  │ <B9>です。「gnome」と「kde」は近代的な X のインターフェイスで、それぞれのデスクトップに適しています (ほかの X                                                                 │  
  │ 環境で利用することもできます)。「エディタ」を用いるとあなたの好きなテキストエディタを用いることができます。「非対話                                                           │  
  │ 的」を選ぶとまったく質問をしなくなります。                                                                                                                                    │  
  │                                                                                                                                                                               │  
  │ 利用するインターフェイス:                                                                                                                                                     │  
  │                                                                                                                                                                               │  
  │                                                                                  ダイアログ                                                                                   │  
  │                                                                                  Readline                                                                                     │  
  │                                                                                  Gnome                                                                                        │  
  │                                                                                  Kde                                                                                          │  
  │                                                                                  エディタ                                                                                     │  
  │                                                                                  非対話的                                                                                     │  
  │                                                                                                                                                                               │  
  │                                                                                                                                                                               │  
  │                                                     <了解>                                                       <取消>                                                       │  
  │                                                                                                                                                                               │  
  └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘  

後続のダイアログです。debconfは、ソフトウェアをパッケージして柔軟に設定/再設定をするための非常に優れた仕組みなので使わない手はないですね。

                   ┌──────────────────────────────────────────────────────────┤ Configuring debconf ├───────────────────────────────────────────────────────────┐                    
                   │ あなたが答えたい質問のうち、最低の優先度のものを選択してください。                                                                         │                    
                   │  - 「重要」は、ユーザが介在しないとシステムを破壊しかねないような項目用です。                                                              │                    
                   │    あなたが初心者か、あるいは急いでいるのであればこれを選んでください。                                                                    │                    
                   │  - 「高」は、適切なデフォルトの回答がないような項目用です。                                                                                │                    
                   │  - 「中」は、適切なデフォルトの回答があるような普通の項目用です。                                                                          │                    
                   │  - 「低」は、ほとんどの場合にデフォルトの回答でかまわないような、ささいな項目用です。                                                      │                    
                   │                                                                                                                                            │                    
                   │                                                                                                                                            │                    
                   │ 注意: ここで何を選択しても、以前に行った質問は dpkg-reconfigure プログラムを使用して表示できます。                                         │                    
                   │                                                                                                                                            │                    
                   │ より低い優先度の質問を無視:                                                                                                                │                    
                   │                                                                                                                                            │                    
                   │                                                                    重要                                                                    │                    
                   │                                                                    高                                                                      │                    
                   │                                                                    中                                                                      │                    
                   │                                                                    低                                                                      │                    
                   │                                                                                                                                            │                    
                   │                                                                                                                                            │                    
                   │                                         <了解>                                           <取消>                                            │                    
                   │                                                                                                                                            │                    
                   └────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘