シェルスクリプトの基本
基本的には拾ってきたものばかりだけど、自分がわかりやすいようにまとめる。
何かあれば順次追加予定。
基本の基本
- 拡張子は
.sh
- 1行目は
#!/bin/sh
とかく(おまじないみたいなもの) - 実行するには
./(ファイル名)
もしくはsh (ファイル名)
基本コマンド
コメント
#
以降はコメントとなる
入出力
read
が入力、echo
が出力
変数
変数名は半角英数字とアンダーバーが使える。
値代入には、=
を前後空白なしで入れる。
型を記述せずにいきなりvar="変数"
とか定義してよい。
が、定数宣言する時は、readonly
を変数名の前に書く。
変数へのアクセスは、変数名の前に$
を入れるか、$
を入れた後に{}
で囲む。
例えば、以下のようなシェルスクリプト(hello.sh)なら
#!/bin/sh # この行はコメントです echo "What's your name? " read NAME mes="Good luck!" echo "Hello, $NAME!" echo "$mes"
出力結果は以下のようになる(入力をKenとした場合)
$ ./hello.sh What's your name? Ken Hello, Ken! Good luck!
特殊変数・特殊文字
$0
スクリプト名
$1~9
引数。n番目の引数が$nとなる。
$#
引数の数
$?
直前実行したコマンドの終了値
特殊文字は\
と併用。例:\*
。
演算子
expr 数字 演算子 数字
(変数に代入するなら両端を`で囲む必要あり)で計算できる
+
、-
、*
、/
、%
、=
、==
、!=
、!
はよくある意味でそのまま
気をつけるべきは以下
-gt
>を表す
-le
<を表す
-o
or
-a
and
-z
文字列が空ならTRUEを返す
-n
文字列に何か指定していればTRUEを返す
配列
ARRAY=(要素1 要素2 ‥)
のように定義する。
n番目の要素を参照する時はARRAY[n]
とすれば良い。
条件分岐・ループ
if文
if [ 条件式1 ]; then 実行文 elif [ 条件式2 ]; then 実行文 else 実行文 fi
for文
for 変数 in 範囲 do 実行文 done
while文
while [ 条件式 ] do 実行文 done
Switch文
case 変数名 in 条件・値1) 実行文 ;; 条件・値2) 実行文 ;; : esac
ループの時のお決まりbreak
やcontinue
も使える
関数
関数を定義するときは以下のようにする。
関数名 () { 実行文 }
関数を実行するときは関数名 引数
で。関数名のあとに()
はいらない
たとえば、以下の関数を実行するときはhello Alice Bob
でいい
hello () { echo "$1: Hello, $2!" }
このとき、Alice: Hello, Bob!
と表示されるはず。
git基本コマンド
最近、将来的に必要になるであろうgitの勉強している。
だが、pushやpullやらプルリクやらよく迷うので
代表的なコマンドを復習ついでに簡単にまとめて残しておく
初期化コマンドと必須コマンド
git init
:リポジトリの初期化
リモートからクローンする場合は必要ないから案外使わないかも
git add
:インデックスにファイルを追加
gitリポジトリのワーキングツリーでファイルを追加しただけでは、
gitリポジトリの管理対象にはなっていない。つまり、commitできない。
commitするためにも、先に必要。
git add filename
とすれば、指定したファイルを追加するが、
git add .
とすれば、全部指定できるので便利。
git commit
:リポジトリの歴史を記録
-mオプションをつけてそのあとに "comment" とすれば
commentがコミットメッセージとなる。
なければ、エディタが起動してコメントを書くことになる。
--amendオプションで直前のコミットのコミットメッセージを修正できる。
git remote add
:リモートレポジトリを登録
例:git remote add origin https://github.com/userA/x-project.git
とすれば、userAのx−projectのリポジトリをリモートリポジトリとして保存する
(cloneしてきたときは、自動でoriginに追加されているらしい)
アドレス間違えた時は、git remote set-url origin [url]
で登録し直す
git push
:リモートリポジトリに送信
例:git push -u origin master
とすれば、originリポジトリのmasterブランチに現在のブランチの内容を保存する。
違うブランチをpushするには、最後にスペースをあけずに:[branch名]
を追加。
-uオプションで、今後git pullで、origin/masterから内容を取得できる。
git pull
:最新のリモートリポジトリを取得
例:git pull origin branchA
とすれば、リモートリポジトリのoriginからbranchAの情報を最新に更新
開発を始める前に更新がないか確認しとかなければ、後々面倒くさいことなったり
するので大事なコマンド
必須ではないけど大事なコマンド
git status
:現在の状態を確認
commit後にこれを実行して「nothing to commit, working directory clean」と出れば
だいたいうまくいっている。絶対必要な操作ではないが、確認は大事。
git log
:コミットログを確認
リポジトリにコミットされたログを確認。
ファイルやディレクトリを指定すれば、それに関するログを確認できる。
-pオプションで差分を確認できる。これも絶対必要な操作ではないがってやつ。
--graphオプションでブランチを視覚的に確認する。
git diff
:変更差分を確認
ワークツリー、インデックス、最新コミット間の差分を確認できる。
何も指定しなければワークツリーとインデックスの差分、
HEADと指定すればワークツリーと最新コミットとの差分、
がそれぞれわかる。
commitする前に、差分を確認する癖はつけたほうがいいらしい。
git branch
:ブランチを一覧表示
新しいブランチ名を指定すれば、その名前のブランチを作成できる
git checkout
:ブランチの切り替え
ブランチを指定して切り替える。
-bオプションで新規のブランチを作成して、それに切り替える。
-のみで1つ前のブランチに戻れる。
git merge
:ブランチをマージする
指定したブランチを、現在のブランチにマージする。
--no--ffオプションで、マージコミットを作成できる
(ブランチからマージしたことを明確に残せる)。
8/1追記:このオプションないって言われた。要調査。
git reset
:歴史を戻る
タイムマシンではない。
--hardオプションに、戻りたい場所のハッシュ値を与えることでそこに戻れる。
ハッシュ値はgit log
やgit reflog
で参照できる。
git rebase -i
:歴史を押しつぶして改変
コミット後に些細なミスを発見し、それを修正したコミットをする時とかに使う。
例えばHEAD~2
とすると、現在のブランチ(HEAD)を含めた2つの歴史を
対象として改ざんする。
この時、エディタが立ち上がるが押しつぶす歴史のpickの記述をfixupに変える。
この操作は怖い気がするのだが、どうなんだろう
ターミナルのおすすめの設定
ふらふらしてたらいいブログを見つけたので紹介。
コピペで絶対動く。説明を妥協しない – joppot
古い記事でも、本当にこのままでうまくいくものが多いから素晴らしい。
このスタンスは見習いたい(もっと画像増やすべきだよな・・・やっぱり)
基本的には本当に書いてある通りにやればいいので
私が余計な補足をする必要はありません
というわけで、今回は幾つかの記事でおすすめされている
ターミナルの設定(.bash_profile)のまとめでもしようかと
※7/26追記:全部.bash_profileに書いても大丈夫だが、.bashrcとの使い分けする方がいい
※詳しくはこちらの記事を参考に
本当に正しい .bashrc と .bash_profile の使ひ分け - Qiita
設定ファイルがないならtouchコマンドでホームディレクトリにでも作ればいい
$ touch .bash_profile $ touch .bashrc
これらのファイルをお好きなエディタで編集していきます
cdコマンドとlsコマンドを一緒にしてしまう
これすごく思ってた。「なんで一緒じゃないのだろう」と。
で、ないなら作れと。天才かと思った。
具体的なコードは以下に
function cdls(){ \cd $1 ls; } alias cd=cdls
2行目のバックスラッシュは絶対に忘れてはいけないとのこと。バグる。
※7/26追記:この設定は.bash_profileに書くより.bashrcに書くほうがいい。
※うるせぇ!俺は全部.bash_profileに書くんだよ!って方は編集後すぐに反映されるわけではないので
$ source .bash_profile
としてやる
ターミナルのカーソルの前のプロンプトに表示されている文字を編集
デフォルトのままだと、ついつい長くなりがちなこれ。
これ編集できるらしい。
詳しくはこれも本家さまの記事を参考にしていただきたいが、
Macターミナルのカーソルの前のプロンプトに表示されている文字をカスタマイズする | joppot
とりあえず短くできるの教えてくれーって人は、
export PS1="\W $ "
この記述を.bash_profileに追加してやってください。私は結構感動した。
色味をつける
これはもう以下を参照してください(サボったわけではありません。これは本家さまのをちゃんと読むべき)
ターミナルに奇麗な色をSolarizedで付ける(一般的な方法) | joppot
ターミナルに奇麗な色をSolarizedで付ける(応用編) | joppot
他にも、いい記事あるので、ぜひ参考にしてください。
ただのブログの宣伝になってしまった。
おわり
Markdown記法の軽いまとめ
Markdown記法そろそろちゃんと覚えたいので よく使うのを簡単にまとめてみる。
で囲っているのがMarkdown記法での書き方
その下にあるのが、その出力
Markdown記法の部分をコードを書くときのやり方でやってるので
「複数行のコード」(下参照)では見にくくなってます・・・・
見出し
見出しの前に#をつける。つけた個数分のレベルになる。
#見出し1 ##見出し2
見出し1
見出し2
強調
**か__で文言を囲む
**強調文字**
強調文字
改行
半角スペース2ついれる
複数改行したければ全角のスペース入れた後に半角スペースを2ついれる
リスト
行頭にアスタリスク(*)+半角スペース1つか、番号ピリオド(1. )
* list1 * list2 または 1. list3 2. list4
- list1
- list2
または
- list3
- list4
インラインコード
インラインコードの場合はバッククオート(`)で文言を囲む
C言語の標準出力は`printf()`です
C言語の標準出力はprintf()
です
複数行のコード
バッククオート3つで囲む
例ではバッククオートを見せるためにバッククオートの前に、半角スペース入れてるけど本当は入れない
最初のバッククオートの後に言語を指定するとそれ用に色づけされる
```java // sample code import java.util.* public class Sample{ public static void main(String[] args){ System.out.println("Hello,World!"); } } ```
// sample code import java.util.* public class Sample{ public static void main(String[] args){ System.out.println("Hello,World!"); } }
引用文
行頭に>を入れる
> これは引用文です
これは引用文です
リンク
URLを直接書くだけ しかし、以下のように文字列に対してリンクを貼ることも可能
[Wikipedia](http://www.wikipedia.com/)
必要になったら随時追加します
Graphviz超入門
レポートとかで有向グラフを書きたいとき、ペイントでやるのは汚いし、時間かかるしで困っていた。
で、それを解決してくれる「Graphviz」というツールがあるらしい。
Graphvizは次のURLからインストーラをダウンロード可能(windows版)。
http://www.graphviz.org/Download_windows.php
(MacOS、Linux版については別途用意されているけど、それはコマンドでインストールしたほうがいいかも。詳しくは、ググればたくさんでてくる。)
以下2.38版での説明。
主に使いそうなのは以下の2つ
dotty.exe:GUIでグラフ描写できる。ただ書きづらそう
gvedit.exe:dotファイルを編集し、グラフを画像として保存、表示する
dotファイルでの基本的な書き方
グラフの種類 グラフ名 { graph [属性="値"; …]; node [属性="値"; …]; edge [属性="値"; …]; "ノードA"->"ノードB" [属性 = "値"; …]; "ノードA"--"ノードB" [属性 = "値"; …]; : }
- グラフの種類:digraph(有向グラフ)または、graph(無向グラフ)
- グラフ名:適当でいいが、グルーピングするときなどに使うらしい
- ○○[属性="値"; …]:○○(グラフ、ノード、エッジなど)について、属性とその値を一括で決めることができる。属性は、shape、label、style、color、fillcolorなどがある。
- ノード -> ノード:ノード間を→で結ぶ。無向グラフなら--で記述する。
例えば、単に
graph sample{ A -- B; A -- C; A -- D; B -- E; }
と書いたら、以下のようなグラフが生成されるけど、もっと複雑になるときに、
ノードやエッジをあらかじめ、先に定義しといたほうが後々記述が楽になる・・と思う
あと、ラベル名を日本語にしたい時は、ノードのfontname属性をmeiryoとかで指定してやる。
名前が同じノードなんだけど、違うノードとして扱いたいときは、
node1[label = "ノード名"] node2[label = "ノード名"]
とでもしてやればいい。
最後に、最近の課題で作ったコードを少しいじったやつとそのグラフを載せて、作成例として終わる。年齢、収入、貯金という属性で株をやっているかどうかというグラフ。
digraph sample{ node[fontname="meiryo"]; edge[fontname="meiryo"]; age[label = "年齢"]; savings[label = "貯蓄"]; income[label = "収入"]; n10[label = "無"]; a4_50[label = "有"]; in_high[label = "有"]; in_low[label = "無"]; sa_high[label = "有"]; sa_low[label = "無"]; age -> n10[label = "10代"]; age -> income[label = "20代"]; age -> savings[label = "30代"]; age -> a4_50[label = "40代"]; age -> a4_50[label = "50代"]; income -> in_high[label = "high"]; income -> in_low[label = "low"]; savings -> sa_high[label = "high"]; savings -> sa_low[label = "low"]; }
Hadoopクラスタ構成への道 ~完全分散編~
※疑似分散までは前記事を参照
Hadoopクラスタ構築への道 ~疑似分散編~ - 8t's BBR
※前記事の続きという形で
準備
まずはHadoopクラスタを組みたいサーバーすべてにHadoopを入れます。
一つ一つ手作業でやってもいいですが、疑似分散までできているサーバーがあるなら、rsyncコマンドを使ってhadoopのディレクトリを丸々コピーしてやればいいと思います。
# 前記事と同じhadoop-2.7.2を使っている場合 rsync -auvz hadoop-2.7.2へのパス コピー先IPアドレス:コピーしたいディレクトリ先のパス
あとは、環境変数の指定(sourceコマンドで反映させるのを忘れないこと)とかjavaをインストールしておけば準備は完了です。
これもpdshコマンドとかを使ってまとめてやれると楽かと思います。
よくわからんし、クラスタの規模もかなり小さいし、一台一台手作業でやるよーって人は前記事を参考に頑張ってください。
設定ファイルの変更
次に各ノードの設定ファイル。
公式にはいろいろと書いてあるが、とりあえず動かすだけなら以下の記述で十分っぽい。
MasterノードとSlaveノード共通の設定
# core-site.xml
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://[masterノードのIPアドレス]:9000</value> </property> </configuration>
<configuration> <property> <name>dfs.replication</name> <value>3</value> </property> </configuration>
# yarn-site.xml
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.resourcemanager.hostname</name> <value>[masterノードのIPアドレス]</value> </property> </configuration>
Masterノードの設定
疑似分散からの続きであれば特に変更はないが、masterノードで
# mapred-site.xml
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>
での記述も確認。
実行
あとはNamenodeのフォーマットして、master、slaveの各ノードでデーモンを起動
# masterノード $ hdfs namenode -format $ hadoop-daemon.sh start namenode $ yarn-deamon.sh start resourcemanager # slaveノード $ hadoop-daemon.sh start datanode $ yarn-daemon.sh start nodemanager
これでうまくいけば、サンプルアプリケーションまで動かせる。
つまったところ
- Datanodeは立ち上げるが、Namenodeとつながらない
これに1週間近く手間取った。logを見ればhostname cannot resolvedとなっている。sshやtelnetはつながるし、Hadoopの設定の何かがだめなことは予想できるのだがいつまでたっても原因がわからず・・・
苦手な英語のサイトまでみてようやく見つけた。
Why Datanode is Denied Communication With Namenode - Rowanto Luo
つまるところ、Namenodeはブラックリストなるものをもっていて、そこにあるIPのやつとは接続しないらしい
(なんでslaveノードがブラックリスト化されてんだよ・・・、てかいつされたんだよ・・・)
というわけで、とりあえずブラックリストにあるIPかどうか調べるのを無効にしてやれとのこと
namenodeのhdfs-site.xmlに
<property> <name>dfs.namenode.datanode.registration.ip-hostname-check</name> <value>false</value> </property>
の記述を追加すればいいだけ。
てかこんなん知らねぇよ。公式に書いてくれ。
- jobが途中から進行しない
ログを見ると、名前解決ができないとのこと。またか。
各ノードの/etc/hostsにそれぞれのノードのIPとhostnameを追加してやる。
まだエラー。また英語のサイト巡りしてみると/etc/hostsのローカルループバック127.0.1.1が駄目とのこと
割り当てているIPアドレスに変えたらなんとかなった。
Hadoopクラスタ構築への道 ~疑似分散編~
※HadoopはCDHではなく、Apacheの公式ページからビルド
※完全分散は別記事。ここでは疑似分散まで
Javaのインストール
まずはjava7をダウンロード ※hadoop-2.7の時点ではjava8はまだ対応していない
# リポジトリ追加 $ sudo add-apt-repository ppa:webupd8team/java # アップデート $ sudo apt-get update # jdk7インストール $ sudo apt-get install oracle-jdk7-installer
↓参考にしたサイト
ubuntu 14.04にOracleJDK7(JAVA)をインストールする - Qiita
Hadoopインストール
基本的にはApacheの公式ドキュメントに沿って行う
Apache Hadoop 2.7.2 – Hadoop: Setting up a Single Node Cluster.
ぐぐるといろんな方が様々なパラメータを追加で設定しているやり方を載せてくれているが、初心者が下手に真似すると爆死します(俺の事)
# HadoopパッケージをHome(好きなとこ)に置く $ wget http://ftp.meisei-u.ac.jp/mirror/apache/dist/hadoop/common/hadoop-2.7.2/hadoop-2.7.2.tar.gz # 解凍 $ tar zxvf hadoop-2.7.2.tar.gz # 環境変数を設定 $ sudo vim /etc/profile
末尾に以下を追加、後々便利なので、余分なものも追加しているが、公式にのっているやつだけもよい
export JAVA_HOME=/usr/lib/jvm/java-7-oracle
export HADOOP_HOME=/home/#ユーザー名/hadoop-2.7.2
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin
# 適用する $ source /etc/profile
ここからHadoop環境の設定
# まずは、etc/hadoop/hadoop-env.sh export JAVA_HOME=/usr/lib/jvm/java-7-oracle export HADOOP_CONF_DIR=/home/ユーザー名/hadoop-2.7.2/etc/hadoop # 次に etc/hadoop/ の core-site.xmlとhdfs-site.xmlに以下の内容を追加 # core-site.xml <configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> </configuration> # hdfs-site.xml <configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration> # localhostにパスフレーズなしで自分に接続できるか確認 $ ssh localhost
SSHで接続できないときは以下のページを参照
複数の仮想マシンを互いにSSHで接続 - 8t's BBR
# ファイルシステムのフォーマット(設定ファイルをいじるたびに必ず行う) $ (bin/)hdfs namenode -format ///pathを通していたらbin/かかなくてよい、以下略 # デーモンの起動 $ (sbin/)start-dfs.sh # デーモンがきちんと起動したか確認。 $ jps
立ち上がっていれば、NamenodeとかDatanodeとかが表示される。
ウェブで確認するには、http://localhost:50070でつながるかどうか
ここから実際にサンプルアプリケーションを動かしてみる
# hdfsのユーザーを作成 $ hdfs dfs -mkdir /user $ hdfs dfs -mkdir /user/<username> # hdfs用のinputディレクトリ作成 $ hdfs dfs -put etc/hadoop input # アプリケーション起動。公式ではgrepでやってる $ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount input output # 出力データ確認 $ hdfs dfs -get output output $ cat output/* # or $ hdfs dfs -cat output/*
ここからYARNの起動。まずは設定ファイルから。
# etc/hadoop/mapred-site.xml <configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration> # etc/hadoop/yarn-site.xml <configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration> # ResourmanagerとNodemanager起動 $ (sbin/)start-yarn.sh
jpsコマンドかウェブで確認
ウェブで確認する場合はポート番号8088で
そして先ほど同様にサンプルアプリケーション動かしてみて、
最後までしっかり動作すればOK