シェルスクリプト入門 その1 入力、出力、変数

はじめに

動機

シェルスクリプトを最近(ようやく?)、自分で書くようになってきました。 スクリプト言語と違うところ及び自分の頭の整理のために書いていきます。

シェルクスクリプトとは

シェルスクリプトとはunixコマンドを一つのファイルにまとめて実行するプログラムです。

利用シーン

  • ログファイルをリネームして移動したりする
  • VPSMacで作成したプログラム(rubypython)を定期的に実行 (cronと組み合わせる)
  • ...

などなど、使えると色々と便利なのは間違いありません!

入力、出力

とりあえず hello world

#!/bin/sh
echo "hello world" # hello world 

と書いて、実行すると、hello worldと出力されます!

$ sh hello.sh
$ hello world

重要なポイントは以下の点です。

  • 文頭に #!/bin/sh と記述。
  • シェルスクリプトunixコマンドが使える
    • 今回は echo を使用
  • コメントは # と記述した後に記述

標準入力、出力

  • read で値を標準入力
  • echoで値を出力します。
#!/bin/sh
read input 
echo "input=$input"
$ sh read.sh
$ hello
$ input=hello

といった形で標準入力、出力が行えます!

変数

重要なポイントは以下の通りです。

  • 変数に値を与える際、 variable=hoge といったようにスペースをつけない
  • 宣言した変数をアクセスする際は 先頭に$をつける。
  • readonly を用いると変数を上書きされない。
  • readonly を解除するには unsetを用いる。
#!/bin/sh
variable=hoge #スペースを入れない
echo $varible #変数にアクセスする際は$をつける
$ sh variable01.sh
$ hoge

また、readonlyと宣言すると、変数の上書きがされません。

#!/bin/sh
variable="変数"
echo "$variable"
readonly variable
variable="変更"
$ sh variable02.sh
$ 変数
$ variable02.sh: line 5: variable: readonly variable

特別な変数

個人的に使用頻度が高いと思われるものに絞ります。

  • $0 [スクリプト名]
  • $1 ~ $9 [引数をアクセス 数字は引数の順番を示す]
  • $$ [実行したプログラムのプロセスID]
#!/bin/sh
echo $0 #special_varable.sh
echo $1 #1つ目の引数を出力
echo $$ #プロセスIDを出力

Atom ショートカットキー

ココココ が素晴らしかったのでメモ。

暇な時、更新していきたい。

出来ること コマンド
カーソルを上に移動 ctr + p
カーソルを下に移動 ctr + n
カーソルを左に移動 ctr + b
カーソルを右に移動 ctr + f
当該の行まで移動 ctr + g
行の先頭まで移動 ctr + A
次単語の移動 option + F
単語を一つ戻る option + B
プロジェクト追加 cmd + shift + o
単語の選択 cmd + d
末尾までカット ctr + k
当該行を移動 cmd + ctr 上下

2017/11/21: カーソル移動追記

【Go言語】スライス

最近、Go言語を勉強しているので、メモがてら書いておきます。

スライスの特徴

容量を増やせば可変長型配列のように使えるようです。 GoはArrayだと要素数は最初に宣言した以上には増やせません。

使い方コード例

package main

import "fmt"

func main() {
  s := []int{2, 3, 5, 7, 11, 13}
  var s1[]int
  var s2[]int
  var s3[]int
  
  s1 = s[1:4]
  fmt.Println(s1)  // [3 5 7]
  s2 = s[:2] 
  fmt.Println(s2) // [2 3]
  s3 = s[1:]     
  fmt.Println(s3) // [3 5 7 11 13]
  fmt.Println(cap(s)) // 配列の容量
  fmt.Println(len(s)) // 配列の長さ
}

make append

package main

import "fmt"

func main() {
  slices := make([]int, 3)
  fmt.Println(slices)  // [0 0 0]
  var slices_append []int
  slices_append = append(slices, 1) // 追加
  fmt.Println(slices_append) // [0 0 0 1]
  fmt.Println(len(slices_append)) // 要素数 4
  fmt.Println(slices_append[2]) //要素にアクセス 0
}

参考

【ruby】キーワード引数と通常の引数組み合わせ

キーワード引数と通常の引数組み合わせ

エラー例

def test_method1(params = {}, hoge: true)
  return params, hoge
end
# こける
$ irb>  test_method1({test: 'test', test2: 'test2'})
$ ArgumentError: unknown keywords: test, test2

エラーとならない

def test_method2(params, hoge: true)
  return params, hoge
end

すると、

# こけない
$ irb(main)>  test_method2({test: 'test', test2: 'test2'})
$ => [{:test=>"test", :test2=>"test2"}, true]

エラーとならない2

もう一つ

def test_method3(hoge: true, **params) # 引数の順序としてキーワード引数が先となる
  return params, hoge
end

すると、

# これもこけない
$ irb(main)>  test_method3({test: 'test', test2: 'test2'})
$ => [{:test=>"test", :test2=>"test2"}, true]

【サーバーレス Lambda】Apexを使ってデプロイ環境を整備する

Lambdaとは

公式によると 

AWS Lambda はサーバーをプロビジョニングしたり管理しなくてもコードを実行できるコンピューティングサービスです。AWS Lambda は必要に応じてコードを実行し、1 日あたり数個のリクエストから 1 秒あたり数千のリクエストまで自動的にスケーリングします。使用したコンピューティング時間に対してのみお支払いいただきます- コードが実行中でなければ料金はかかりません。 ...以下、略

と書いてあります。

難しすぎますね。。

個人的に重要な点

個人的にLambdaの重要なところは以下の3点だと思います。

  • 1.サーバー管理、言語環境設定などをせず、コードを実行出来る
  • 2.他のAWSサービスと連携がしやすい
  • 3.使用言語: Node C# JAVA Python

Lambdaの利点

前述したように、サーバー構築を一回でもやったことがある人なら認識あるかもしれないんですが、 新しいインスタンスVPSを立ち上げるのって結構だるいです。

Lambda を使えば環境構築も整備してくれて、すぐに実行出来ます。 そして、AWSのサービス群である CloudWatchAPIGatewayを使えば cron job や 面倒なAPIを作成することが出来ます!

Lambda 面倒な点?

まずはじめにLambda実行方法をあげてから面倒な点を述べます。

Lambdaの実行方法(GUI)形式で乗っ取ると以下のような手順を踏まえます。 注) 以下、python を想定

  • 1 python プログラム作成
  • 2 python プログラム、標準外ライブラリをフォルダに一式入れてZIP化、アップロード
  • 3 実行環境設定 (メモリ、実行時間など)

面倒なのは2と3の実行手順です。標準外のライブラリをダウンロードして ZIP化、さらには実行環境設定などをいちいち設定しなくてはいけません。

Apexとは

Apexは上述した、Lambdaの面倒な点をサポートするデプロイツールです。 Apex公式

利点

利点は以下の通りです。

  • プロジェクトごとに共通の設定を持たせることが出来る
  • プログラムファイルは自動でZIP化し、デプロイ
  • エイリアスを用いることが出来るので、ロールバックやアップデートも楽
  • Go言語が使用可 (デフォルト使用言語: Node C# JAVA Python)

利用方法

想定言語:python(ローカルでパッケージ管理ツール pip がインストール)

apex環境構築

# IAMで access key と secret access keyを取得しておくこと
# コマンドラインでAWSを操作出来るパッケージインストール

$ pip install awscli
$ aws help  # install 確認
$ aws configure
# 以下を入力
# AWS Access Key ID [**********]:
# AWS Secret Access Key [**********]:
# Default region name [ap-northeast-1]:
# Default output format [json]:

apex install

# apex install
curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sh
apex version # install確認

apex 実行

$ mkdir apex-test 
$ cd apex-test/
$ apex init #project name descriptionを記入

apex initを実行すると以下のようなプロジェクトフォルダが作成されます。 初期設定はjsになるようです。。

.apex-test
│
├── functions
│   └── hello
│       └── index.js 
└── project.json # プロジェクトの固有設定

ので、python仕様と説明用に以下のようにしておきます。

.apex-test
│
├── functions
│   └── hello
│       │── function.json # function固有の設定(←デプロイされるプログラムの設定)
│       └── main.py # デプロイプログラム
└── project.json # プロジェクトの固有設定

project.json

{
  "name": "blog-test",
  "description": "test",
  "memory": 128, # 使用メモリ、CPUと連動
  "timeout": 5, # 秒
  "role": "[AWS-ROLE]",
  "environment": {} # 環境変数設定 pythonの場合、os.environ["#####"]で取得可
}

ここでは各プロジェクトの共通設定を記述しています。

function.json

用途:各ファンクション固有の環境設定を記載する。 なお、project.jsonの内容は継承されます。

{
  "description": "python functions",
  "runtime": "python3.6", # 実行環境
  "memory": 128,
  "timeout": 20,
  "hooks": {
  "build": "pip install -r requirements.txt -t ./", # デプロイ前の処理
  "clean": "rm -rf */" # デプロイ後の処理
  },
  "environment": {
    "????_API_KEY":"######",
    "URL":"https://hoge.com"
  }
}

このようにLambdaファンクション固有の設定を記述することが出来ます。

なお、hooksの内容は

  • build(deploy前):記述内容はlambdaデプロイ時に標準外パッケージをインストールし、デプロイ
  • clean(deploy後):buildでインストールした標準外パッケージを削除

となります。

上記のようなjsonファイルを作成することで、lambdaの面倒な点

  • 1.プログラム、標準外ライブラリをフォルダに一式入れる処理)
  • 2.実行環境設定 (メモリ、実行時間など)

を自動化することが出来ます。

apex コマンド

少し長くなってしまったので、個人的に有用だと思うコマンドをまとめておきます。

# 新規プロジェクトを作る
apex init
# 当該プロジェクト内のファンクションをデプロイ
apex deploy
# 当該プロジェクト内の特定のファンクションをデプロイ
apex deploy {FunctionName}
# invoke: deploy後の実行結果をローカルで試す。
apex invoke {FunctionName}
# event の受け渡し
apex invoke {FunctionName} < event.json
# エイリアス作成
apex alias {AliasName} {FunctionName}
# エイリアスのデプロイ
apex deploy -a {AliasName}

apex rollback -v n  # n:数字
apex rollback # 一個前に戻す
apex rollback -a {AliasName} # エイリアスロールバック

最後に

最近、Lambdaをはじめたのですが、面白いのでApexを用いて がしがし有用なプログラム作っていきたいです\(^o^)/

docker 使うコマンド

コマンド

気が向いた時に更新していきます。

$ docker search イメージ名
#コンテナのもととなるイメージを検索 
$ docker pause コンテナ識別子
# 起動中のコンテナを停止
$ docker pull イメージ名
$ dcoker attach  
# 稼働しているコンテナの接続
$ docker top
#稼働コンテナのプロセス確認
$ docker port
#稼働コンテナのポート確認
$ docker commit
#コンテナからイメージ作成

docker 頭の整理

docker for mac

Macでdockerを使う際はdocker for mac という素晴らしいアプリが ある。これは

  • docker
  • docker-machine
  • docker-compose

というありがたいツールがオール・インワンになっているアプリケーションです。 docker-machineは前回話した通り、仮想マシンを作成するものです。 docker-composeは後々まとめる予定。。

仮想マシンにログインするには

docker ssh とコマンドを打てばおkです。Vagrantみたいですね。

イメージとは

dockerの仮想マシン上にログインしたものの、 何もない状態ではつまらないので、docker上でruby環境やらpython環境 構築したいですね。その際には、docker imageをダウンロードして使います。

docker imageとは、アプリ実行に必要なプログラム、ミドルウェアを一つにまとめたものです。通常はプログラムとミドルウェアを別々に管理しておくようです。

docker image は自分で作成することもできますが、

docker hubを探して使うことも出来ます (便利!)

イメージを取得するするには

docker pull イメージ名 を行えばうまくいきます。

githubみたいです。