• Like
シェルスクリプトを極める
Upcoming SlideShare
Loading in...5
×

シェルスクリプトを極める

  • 125 views
Uploaded on

シェルスクリプトワークショップの資料です。

シェルスクリプトワークショップの資料です。

More in: Engineering
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
125
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
3
Comments
0
Likes
4

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. シェルスクリプトを極めるシェルスクリプトを極める USP 友の会 今泉光之 @bsdhack http://bsdhack.org
  • 2. 仕事で使えるシェルスクリプト 2 講師講師 ● 今泉光之  UNIX/Linux環境でのプログラミングを中心に、ネットワークや インフラなども含め20年以上に渡る経験だけは積んできました。  当初はC言語でコンパイラ、Xサーバ、ドライバ、TCP/IPによる 通信などシステム系のプログラミングが主でしたが、最近はPerl やPHPなどのWeb向けのLLも使っています。
  • 3. 仕事で使えるシェルスクリプト 3 fdfd を活用するを活用する ● fd とはファイルディスクリプタの略 – オープンしたファイルの識別子 – 標準入力は 0 – 標準出力は 1 – 標準エラー出力は 2 – シェルではリダイレクト記号の前に数字 ● 3> ファイル fd3 をファイルにリダイレクト ● 4< ファイル fd4 をファイルからリダイレクト ● 5<&- fd5 をクローズ ● 6>&7 fd7 を fd6 に複製 (fd6 を fd7 にリダイレクト
  • 4. 仕事で使えるシェルスクリプト 4 ● プロセスの出力同士を diff(1) で比較する – 3<&0 で標準入力 (fd0) を fd3 に複製 – コマンド 1 の出力が fd3 に出力される – /dev/fd/3 からの入力がコマンド 1 の出力 fdfd の活用方法①の活用方法① $ diff <( コマンド 1 ) <( コマンド 2 ) $ コマンド 1 | ( コマンド 2 | diff /dev/fd/3 -) 3<&0
  • 5. 仕事で使えるシェルスクリプト 5 fdfd の活用方法②の活用方法② ● パイプの途中のプロセスの終了コード – コマンド 1 の $? を 1>&3 で fd3 に出力 – fd3 の内容を 3>&1 で ret1 に格納 $ exec 3>&1 ret1=`{ { コマンド 1; echo $? 1>&3; } | コマンド 2; } 3>&1` ret2=$?
  • 6. 仕事で使えるシェルスクリプト 6 fdfd の活用方法③の活用方法③ ● ループ処理での活用 exec 3<&0 0<<EOF ` コマンド ` EOF while read line do : done exec 0<&3 3<&-
  • 7. 仕事で使えるシェルスクリプト 7 fdfd の活用③の活用③ – exec 3<&0 で fd0 を fd3 に複製 – exec 0<<EOF でヒアドキュメントを fd0 として使用 – exec 0<&3 で複製した fd0 を復帰 – exec 3<&- で fd3 をクローズ – パイプを使わないのでプロセスが生成されない
  • 8. 仕事で使えるシェルスクリプト 8 fdfd の実装①の実装① ● コマンド > ファイル – fd = open( ファイル , O_WRONLY|O_CREAT|O_TRUNC); ● ファイルを出力モードで open – dup2(fd, 1); ● FD1( 標準出力 ) をクローズした後で fd を 1 に複製する 結果 fd が標準出力として使われる
  • 9. 仕事で使えるシェルスクリプト 9 fdfd の実装②の実装② ● コマンド > ファイル 2>&1 – fd = open( ファイル , O_WRONLY|O_CREAT|O_TRUNC); ● ファイルを出力モードで open – dup2(fd, 1); ● FD1( 標準出力 ) をクローズした後で fd を FD1 に複製する – dup2(1, 2); ● FD2( 標準エラー出力 ) をクローズした後で FD1 を FD2 に複製する 結果 fd が標準出力、標準エラー出力として使われる
  • 10. 仕事で使えるシェルスクリプト 10 fdfd の実装③の実装③ ● コマンド 1| コマンド 2 – pipe(fd[]); ● パイプを生成 – コマンド 1 側 dup2(fd[1], 1); ● コマンド 1 の標準出力をパイプの出力側に複製する – コマンド 2 側 dup2(fd[0], 0); ● コマンド 2 の標準入力をパイプの入力側に複製する 結果コマンド 1 の標準出力がコマンド 2 の標準入力になる
  • 11. 仕事で使えるシェルスクリプト 11 evaleval の活用①の活用① ● 配列的な変数アクセス # $1: 配列名 # $2: インデックス # $3-: 値 setarray() { _index_="__`echo $1 $2 | sed -e 's/ //g'`" shift 2 eval $_index_'='"$@" }
  • 12. 仕事で使えるシェルスクリプト 12 evaleval の活用②の活用② ● 配列的な変数アクセス # $1: 配列名 # $2: インデックス getarray() { eval echo '${'__`echo $* | sed -e 's/ //g'`'}' }
  • 13. 仕事で使えるシェルスクリプト 13 ファイルのオーバーライドファイルのオーバーライド ● 元ファイルを書き替える – ① でファイルが読み込みモードでオープンされる。 – ② でオープンされたファイルが削除される。 – ③ で新しい(別な)ファイルが書き込みモードでオープンされる。 ● ① のファイルと③のファイルはたまたま同じファイル名なだけで、 inode が異なっているので OS からは別なファイル扱いなので正しく動作する。 $ コマンド < ファイル > ファイル # 絶対ダメ! $ (rm ファイル ; コマンド > ファイル ) < ファイル ② ③ ①
  • 14. 仕事で使えるシェルスクリプト 14 排他処理①排他処理① ● シェルスクリプトでの排他処理 – test(1) と touch(1) の間に他のプロセスの test(1) が実行されると 排他処理が失敗する lockfile="/var/tmp/`basename ${0}`" test -f ${lockfile} || touch ${lockfile}
  • 15. 仕事で使えるシェルスクリプト 15 排他処理②排他処理② ● シェルスクリプトでの排他処理 – シンボリックリンクの作成は atomic – PID をリンクする事でロックしたプロセスが特定できる lockfile="/var/tmp/`basename ${0}`" if ln -s $$ ${lockfile} 2> /dev/null then : # メイン処理を実行 else echo "${0}: exist another instance" 1>&2 exit 255 fi trap 'rm -f ${lockfile}; exit' 0 1 2 3 11 15
  • 16. 仕事で使えるシェルスクリプト 16 キャピタライズ①キャピタライズ① ● 英単語の先頭文字を大文字に変換する – awk を利用した方法 ● awk 組み込みの substr() 、 toupper() を使用する $ echo "foo" | awk '{ print toupper(substr($0, 1, 1)) substr($0, 2, length($0) - 1) }'
  • 17. 仕事で使えるシェルスクリプト 17 キャピタライズ②キャピタライズ② ● 英単語の先頭文字を大文字に変換する – sed を利用した処理 ● sed 単体では実現できないのでコマンド列を出力して eval eval `echo "foo" | sed 's/(.)(.*)//bin/echo -n 1 | tr "[a-z]" "[A-Z]"; echo 2/g'`
  • 18. 仕事で使えるシェルスクリプト 18 exex を活用する①を活用する① ● ファイルの行操作に ex を活用する – 直接行の追加や削除が可能(一時ファイル不要) – 実は vi なので正規表現など強力な編集操作が可能 – echo やヒアドキュメントで編集コマンドを指定可能
  • 19. 仕事で使えるシェルスクリプト 19 exex を活用する②を活用する② ● 行追加処理 – 行番号で指定した行の下にコンテンツを挿入する – `.' で挿入モードを終了し `w!' で内容をファイルに出力する $ /bin/ex -s ファイル << EOF 行番号 a コンテンツ コンテンツ : . w! EOF
  • 20. 仕事で使えるシェルスクリプト 20 exex を活用する③を活用する③ ● 行削除処理 – 行番号で指定した行を削除する – `w!' で内容をファイルに出力する $ /bin/ex -s ファイル << EOF 行番号 d w! EOF
  • 21. 仕事で使えるシェルスクリプト 21 exex を活用する④を活用する④ ● 行番号を指定した行置換処理 – 行番号で指定した行のパターンを置換文字列に置換する – `w!' で内容をファイルに出力する $ /bin/ex -s ファイル << EOF 行番号 s/ パターン / 置換文字列 / w! EOF
  • 22. 仕事で使えるシェルスクリプト 22 exex を活用する⑤を活用する⑤ ● パターンを指定した行置換処理 – 最初に発見したパターンを置換文字列に置換する – s の後ろの連続した `//' は直前の正規表現(パターン)を示す – `w!' で内容をファイルに出力する $ /bin/ex -s ファイル << EOF / パターン /s// 置換文字列 / w! EOF
  • 23. 仕事で使えるシェルスクリプト 23 exex を活用する⑥を活用する⑥ ● ファイルから指定された行を削除する – 元のファイル (basefile) には複数の行が含まれている – 削除する行は別なファイル (target) に格納されている – target ファイルには行番号が 1 行ずつ格納されている$ cat basefile first line second line third line : : $ cat target 2 3 5 : :
  • 24. 仕事で使えるシェルスクリプト 24 exex を活用する⑦を活用する⑦ ● パターンを指定した行置換処理 – 削除済みの行を考慮する必要がある → 2 行目を削除すると今までの 3 行目が 2 行目になる – ex で行を削除する – awk で削除した行を考慮した行番号に対する行削除を出力 $ sort target | awk '{ printf "%ddn", $1-(NR-1); } END { print "w!" }' | ex -s basefile