As rookie

ルーキーインフラエンジニアがインフラのこと以外も結構書いてしまうブログ

Linuxのシングルクォートとダブルクォート(?日坊主)

  • この記事はsolo_advent_calender 2016年12月9日のものです。

こんにちは ショート advent calender9日目です。

金曜日に書き忘れ、土曜日にまとめて書こうと思っていると、土曜日も気づいたら終わっている。そんなことありますよね。

はい。

シングルクォート'' の場合は単純に文字列として出力する。 ダブルクォートは"" の場合は変数展開してくれる。です

$ hoge=neko # 変数hogeに文字列nekoを入れる

$ echo hoge 
hoge

$ echo $hoge # 変数を表示するには先頭に$をつける
neko

$ echo '$hoge' # $hogeを文字列として表示
$hoge

$ echo "$hoge" #変数を展開して表示
neko

$ echo "I love $hoge" # 文字列に変数を埋め込む
I love neko

$ echo '$hoge' is "$hoge" # 
$hoge is neko

色んなshell(8日坊主)

  • この記事はsolo_advent_calender 2016年12月8日のものです。

こんにちは ショート advent calender8日目です。

shellには様々な種類があるそうです。

僕は普段bashを使っています。bashは多くのlinuxディストリビューションで標準のshellとなっているようです。

普段bashを使っていますといいましたが、bashbashとして意識したことがありませんでした。ITに触れ出した時からbashでした。エンジニアとして生まれた時からbashだったんです。

東京で生まれた赤子が東京で過ごしていて、東京で過ごしている認識がないようなものです。ちょっと前に神奈川や千葉を知ったのです。そして今神奈川と千葉の事を調べようとしているのです。

大阪で生まれた赤子が大・・・

ということで、色々なshellについてしらべました。

まず列挙すると

色々なshell

*shell名 *コマンド
Bourneシェル sh
Bourne Again shell bash
Cシェル csh
tcsh tcsh
Kornシェル ksh
Zシェル zsh

それぞれの特徴(ソフトタッチ)

  • sh

初代シェルはBourneシェル ことshUNIXの標準的なシェルです。

shの改良版。Linuxディストリビューションの標準的なシェル

C言語に似たスクリプトが利用できるシェル

cshの改良版。特にユーザーインターフェイスの部分を中心に拡張されたシェル

コマンド行をWYSIWYG風の方法で編集することができる。などshの完全上位互換

kshbashtcshの機能を取り入れたもの

と簡単にまとめるとこんな感じ(Wiki Pediaより抜粋)

見る感じkshbashtcshの機能を取りれたzshってのが一番すごそう!

bashからzshに移行する日は来るのだろうか。メリットを理解して良さそうならzshを普段使いしていこうとおもいます!

bashが難波でtcshが鶴橋でksh天王寺

遊べる、飲める、買い物できるで

zshが梅田みたいな感じっぽいですね。路線図的にもJRでもいける、御堂筋線でもいける。

僕はこれから梅田に活動拠点を変えようとしている若者の気持ちです。

ansibleで多重ループ subelements編 (7日坊主)

  • この記事はsolo_advent_calender 2016年12月7日のものです。

こんにちは ショート advent calender7日目です。

今回は6日目で軽くふれていたansibleのloop構文with_subelements を使っていきます。

mokicks.hatenablog.com

公式サイト Loops — Ansible Documentation

まずはvarsファイルを用意します。

# group_vars/all
yum_list
  - state: present
    package:
      - vim
      - unzip
  - state: latest
    package:
      - nginx
      - bind-utils

以前の記事とは違い一つのディクショナリを用意するだけで大丈夫そうです。 JSONだと

{ yum_list: [ { state: present, package: [ vim, unzip ] }, { state: latest, package: [ nginx, bind-utils ] } }

こういう感じです。

yumモジュールで vimunzip はstateをpresentで実行しnginxbind-utils はstateをlatestで実行するようになる予定です。

それに対応したtaskがこちら

# tasks/main.yml
---
- name: install by yum
  yum: name={{ item.1 }} state={{ item.0.state }}
  with_subelements:
    - "{{ yum_list }}"
    - package

with_subelements は与えられたリストを順に展開し,ネストされたリストのキーを判定しその値を使います。

展開して取り出した値を扱いたい場合は {{ item.0 }} {{ item.1 }} のように与えた順に指定します。

流れを書くと

まず

  - state: present
    package:
      - vim
      - unzip

で一回目のloopでこの値を渡します。

次に、 {{ item.1 }}でpackageの中身であるvimunzip を順に取り出します。

{{ item.0.state }} でstateのpresentが取り出されれます。

上記のpackageのループが終わると

  - state: latest
    package:
      - nginx
      - bind-utils

の値を渡します。

実行結果は以下のようになりました

TASK [loop_test : install by yum] **********************************************
ok: [vagrant] => (item=({u'state': u'present'}, u'vim'))
ok: [vagrant] => (item=({u'state': u'present'}, u'unzip'))
ok: [vagrant] => (item=({u'state': u'latest'}, u'nginx'))
ok: [vagrant] => (item=({u'state': u'latest'}, u'bind-utils'))

ネストされているものでループしたいときはこのようにwith_subelements を使うのが良いでしょう

以上

ansibleで多重ループ(6日坊主)

  • この記事はsolo_advent_calender 2016年12月6日のものです。

こんにちは ショート advent calender6日目です。

ansibleで多重ループについて書きます!

ansibleでのループの構文はwith_items を使います。それはご存知ですか?

# task
- name: install by yum
  yum: name={{ item }} 
  with_items:
    - vim
    - unzip

というふうにwith_itemsでリストを与えてその中身(item)でタスクを実行することができます。

この場合だとvimunzipyumでinstallするということですね。

また、あらかじめgroup_varsなどにリストを用意しておいて

# group_vars/all
yum_list:
  - vim
  - unzip
# task
- name: install by yum
  yum: name={{ item }} 
  with_items: "{{ yum_list }}"

というふうにすれば、上のものと同じことができます.

多重ループをするにはどうすれば良いでしょう?

どうやらloop-controlとういものがあるようです。 Loops — Ansible Documentation

通常with_itemsでリストから値を取り出したときリストの中身はitem という変数に格納されて扱われます。

ですがこのloop-controlというものを使うとitem の名前を変えることができるのです。

サンプルでは

- include: inner.yml
  with_items:
    - 1
    - 2
    - 3
  loop_control:
    loop_var: outer_item

# inner.yml
- debug: msg="outer item={{ outer_item }} inner item={{ item }}"
  with_items:
    - a
    - b
    - c

というふうになっています。inner.ymlをインクルードするのをwith_items でループさして、その中身はouter_item という変数に入るというtaskになっています。公式の説明では

2.0では、with_loopsとtask includesを使用することができます(ただし、プレイブックは含まれません)。 これにより、一連のタスクをワンショットでループする機能が追加されます。 不可能なデフォルトでは、各ループのループ変数項目が設定され、これらのネストループは「外側」ループのitemの値を上書きします。 2.1の時点で、loop_controlオプションを使用して、ループに使用する変数の名前を指定できます。(google翻訳のコピペ)

includeするのはtaskのincludeだけのようです。

  loop_control:
    loop_var: outer_item #outer_itemというループ用の変数を定義

で変数名を定義します。

上のyumの例でいくと(yumのときこんなことするはずないが)

# group_vars/all
yum_list:
  - vim
  - unzip
  - nginx
  - mysql

yum_state:
  - present
  - latest
# main.yml
- name: install by yum
  include: inner.yml
  with_items: "{{ yum_state }}"
  loop_control:
    loop_var: outer_item
# inner.yml
- name: install by yum
  yum: name={{ item }} state={{ outer_item }}
  with_items: "{{ yum_list }}"
  

stateがpresetとlatestで両方インストールするという わけのわからないtaskになってしまったが複数のループを使用するときはこういうふうな書き方になりそうです。

また

yum_list
  - statet: present
    package:
      - vim
      - unzip
  - statet: latest
    package:
      - vim
      - unzip

というvarsをつくったならwith_subelementsというloopを使えば子要素でloopできるそう。この記事は明日書く予定です

bashコマンド(5日坊主)

  • この記事はsolo_advent_calender 2016年12月5日のものです。

こんにちは ショート advent calender5日目です。

bash使っている人多いと思います。

bashコマンドもあります。

man bash
bash は、標準入力やファイルから読み込んだコマンドを実行する、 sh 互換の
       コマンド言語インタプリタです。 bash には、Korn シェルや C シェ ル  (ksh
       や csh) の便利な機能も採り入れられています。

正確にはコマンド言語インタプリタだそうです。

bash -c で入力を文字列から読み込んでくれます。

# 同じ結果が返ってくる
$bash -c "ls"

$ls

ansibleでshellモジュールを利用するときに

---
shell: ls -la

とかしますが、shellモジュールでsedgrep などで文字を検索するときにコロン(:)が入っているとansibleではエラーになります。

これを

shell: bash -c "grep :"

とするとコロンもコマンドの一部として扱うことができます。

bash -l環境変数読みこみなので、pyenv等のルート意外のホームディレクトリにインストールされるコマンドも実行できます。

become: False
shell: bash -lc "pyenv versions"

bash周りのファイル群(4日坊主)

  • この記事はsolo_advent_calender 2016年12月4のものです。

こんにちは ショート advent calender4日目です。

man bash
-- 略 --
ファイル
       /bin/bash
              bash の実行ファイル。
       /etc/profile
              システム全体用の初期化ファイル。ログインシェルが実行します。
       ~/.bash_profile
              個人用の初期化ファイル。ログインシェルが実行します。
       ~/.bashrc
              対話シェルごとに実行される、個人用の起動ファイル。
       ~/.bash_logout
              個人用のログインシェル後処理ファイル。ログインシェルの終了時に実行されます。
       ~/.inputrc
              個人用の readline 初期化ファイル。
-- 略 --

.bash_profile.bashrc に何かを追記することはありますが、.bash_logout は使ったことがなかったので使ってみました。

vim ~/.bash_logout
# ~/.bash_logou
d=`date`
p=`pwd`
echo ${d} ${p} >> logout.log
echo "bye" 

ログアウト時に最後にいたディレクトリを追記していくものです。これぐらいしか思いつきません。

cat logout.log

2016年 12月 4日 日曜日 23:48:27 JST /home/mokicks

ansibleでpyenvいれる(3日坊主)

  • この記事はsolo_advent_calender 2016年12月3のものです。

こんにちは ショート advent calender3日目です。

ansibleでDjangoの開発環境を準備するために作りました。

pyenvで指定のバージョンのpythonをインストールするところまでです。

ディレクトリ構成はこんな感じです

pyenv/
├── files
│   └── bashrc
├── handlers
│   └── main.yml
└── tasks
    └── main.yml

bashrcをコピーする方式なので開発マシンに入ってbashrcを書き換えてもう一度実行すると初期状態にもどってしまうので、ファイルの存在を確認するようにしています。

tasks/main.yml

---
- name: clone pyenv
  become: False
  git: repo=git://github.com/yyuu/pyenv.git dest=~/.pyenv accept_hostkey=yes

- name: check bashrc
  become: False
  stat: path=~/.bashrc
  register: is_bashrc
  ignore_errors: yes

- name: copy bashrc
  become: False
  copy: src=bashrc dest=~/.bashrc
  notify: source bashrc
  when: not is_bashrc.stat.exists

- name: check python version {{ python_version }}
  become: False
  shell: bash -lc "pyenv versions | grep {{ python_version }}"
  register: result
  ignore_errors: yes

- name: install {{ python_version }}
  become: False
  shell: bash -lc "pyenv install {{ python_version }}"
  when: result|failed

- name: set global {{ python_version }}
  become: False
  shell: bash -lc "pyenv global {{ python_version }}"

handlers/main.yml

---
- name: source bashrc
  shell: bash -lc "source bashrc"

files/bashrc

# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

export PYENV_ROOT="${HOME}/.pyenv"
if [ -d "${PYENV_ROOT}" ]; then
    export PATH=${PYENV_ROOT}/bin:$PATH
    eval "$(pyenv init -)"
fi

# User specific aliases and functions

group_varsのall等に

# バージョンを指定する
python_version: 2.7.11

を用意すれば

pyenvが開発環境にインストールされます。 あとはpipをインストールしてDjangoをpipでインストールすればDjangoを扱えるようになります。

この部分も後ほどansibleで書こうとおもいます。