Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
シェル芸のせかい / the Shellgei World
Ryoto Saito
March 09, 2020
Programming
2
840
シェル芸のせかい / the Shellgei World
Ryoto Saito
March 09, 2020
Tweet
Share
More Decks by Ryoto Saito
See All by Ryoto Saito
CTFで学ぶPHPセキュリティ
ryotosaito
3
2.3k
Other Decks in Programming
See All in Programming
Practical Advanced Kotlin in Practice
rock3r
3
130
Keep Your Cache Always Fresh With Debezium
gunnarmorling
0
170
機能横断型チームにおける技術改善
takeshiakutsu
3
390
dbtとBigQueryで始めるData Vault入門
kazk1018
0
170
WindowsコンテナDojo : 第1回 Visual StudioでWindowsコンテナアプリ作成
oniak3ibm
PRO
0
320
Where and how to run UI tests (Droidcon London, 2021)
nonews
0
200
職場にPythonistaを増やす方法
soogie
0
170
The future of trust stores in Python
sethmlarson
0
180
Improve Build Times in Less Time
zacsweers
6
2.7k
Get Ready for Jakarta EE 10
ivargrimstad
0
1.7k
확장 가능한 테라폼 코드 관리 (Scalable Terraform Code Management)
posquit0
1
290
あなたの会社の古いシステム、なんとかしませんか?~システム刷新から考えるDX化への道筋とバリエーション~/webinar20220420-systems
grapecity_dev
0
120
Featured
See All Featured
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
226
15k
Fontdeck: Realign not Redesign
paulrobertlloyd
73
4.1k
Building Adaptive Systems
keathley
25
1.1k
For a Future-Friendly Web
brad_frost
164
7.4k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
38
12k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
237
19k
A Tale of Four Properties
chriscoyier
149
20k
How to train your dragon (web standard)
notwaldorf
57
3.8k
A better future with KSS
kneath
225
15k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
350
21k
Mobile First: as difficult as doing things right
swwweet
212
7.5k
Build The Right Thing And Hit Your Dates
maggiecrowley
19
1.1k
Transcript
シェル芸のせかい Ryoto (@systemctl_ryoto) 2020/03/09 Uedalab Meetup 1
こんにちは 今日はシェル芸のお話をします $ echo こんにちは $ echo すましを話おの芸ルェシは日今 | rev
2
$ w3m https://ja.wikipedia.org/wiki/シェル 芸 | grep ^シェル芸 -A 5 シェル芸[編集]
シェル芸とは、主にUNIX系オペレーティングシステムにおいて「マ ウスも使わず、ソースコードも残さず、GUIツールを立ち上げる間 もなく、あらゆる調査・計算・テキスト処理を CLI端末へのコマンド 入力一撃で終わらせること」(USP友の会会長・上田隆一による定 義^[9])である。この技術を持つ人物を指すシェル芸人という呼び 方も存在する^[10]。 3
シェル芸モチベーション • コマンド実行を効率化する • シェルの機能を最大限利用する • やりたい動作を素早く実現する • とっさの時のサーバトラシュー力が向上する •
GUIよりCLIの方が軽量、ソフトウェアも多い[要出典] 4
シェル芸とその基礎:標準入出力(stdio) 5
シェル芸を始める前に:標準入出力 • 入出力の抽象 • 標準入力(0)、標準出力(1)、標準エラー出力(2) • ファイルディスクリプタ番号は固定 • デフォルトはターミナル(tty)にバインドされている •
リダイレクト(<, >, <<, >>, etc.)によってファイルなどへ変更可 能 シェル芸とその基礎:標準入出力 (stdio) 6
$ echo terminal >$(tty) $ echo stdout >/dev/stdout terminal #
ターミナルへ直接出力 stdout # 標準出力へ出力(=何も指定しないのと一緒) 別の画面のttyに向けて echo hello >/dev/tty?? すると…? program /dev/tty?? /dev/stdout シェル芸とその基礎:標準入出力 (stdio) 7
$ echo うっしっし | cowsay # pipe “|” は前のプロセスのstdoutと後のstdinをつなげる #
これで立派なシェル芸人 _________________ < うっしっし > ----------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || pipe stdout echo stdin cowsay シェル芸とその基礎:標準入出力 (stdio) 8
シェル芸の沼にハマると • シェルでCMSを作って運用し始める https://github.com/ryuichiueda/bashcms2 • シェルでHTTPサーバを作り始める https://github.com/ryotosaito/shttpd • 少ない記号種でdateを実行するゴルフ?が始まる https://twitter.com/minyoruminyon/status/1152161173158055936
• シェル芸をTwitterに投下できるbotを作る https://github.com/theoremoon/ShellgeiBot • VUIでシェル芸をしたくなった結果呪文詠唱を始める https://speakerdeck.com/amanoese/vuidesieruyun-woshi-xing-dekiruyounisitemita 9 シェル芸とその基礎:標準入出力 (stdio)
$ echo fd1 >/dev/fd/1 $ echo alias >&1 fd1 #
ファイルディスクリプタ1 (= stdout) に出力 alias # >&1 は >/dev/fd/1のエイリアス まとめ:標準出力の表し方 • /dev/stdout • /dev/fd/1 • >&1 シェル芸とその基礎:標準入出力 (stdio) 10
$ echo stderr >/dev/stderr $ { echo error >&2; }
2>error.txt stderr # 標準エラー出力 → ttyに出力 # “error” を標準エラーに出力 → さらに error.txt に転送 # 標準出力も標準エラーもデフォルトはttyにバインド シェル芸とその基礎:標準入出力 (stdio) 11 program /dev/tty?? /dev/stdout /dev/stderr /dev/tty?? error.txt
$ man life 2>&1 | cowsay $ man life |&
cowsay 標準エラー出力をpipeしたい場合は、 • プロセス中で標準出力にリダイレクトする • 標準エラー出力も一緒にpipeする ’|&’ を使う __________________________ < No manual entry for life > -------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || シェル芸とその基礎:標準入出力 (stdio) 12
シェル芸の基礎:シェル機能 13
コマンド出力をコマンド文字列として認識する Command substitution $ docker rm $(docker ps -aq) #
dockerのコンテナを全て削除する # docker ps -aqはコンテナIDをリストする # 展開対象は標準出力(stderrはttyに垂れ流される) シェル芸の基礎:シェル機能 14
$ paste <(seq 1 3) <(seq 4 6) 1 4
2 5 3 6 # equivalent to # seq 1 3 >13.txt; seq 4 6 >46.txt; paste 13.txt 46.txt $ echo <(seq 1 4) <(seq 4 6) /dev/fd/63 /dev/fd/62 コマンド出力をファイルとして認識する Process Substitution シェル芸の基礎:シェル機能 15
その他Bashの有用な機能 • /dev/tcp/host/port でネットワークリダイレクト ◦ exec 3<>/dev/tcp/localhost/80 ◦ echo -e
"GET / HTTP/1.1\r\n\r\n" >&3 ◦ while read line <&3; do echo $line; done • command1 || command2で失敗時処理 • ((i++))などの演算や、for ((i=0;i<10;i++))の記述 • declare -n や local -n で変数の参照を得る • {a,{b,c}d}e → ae bde cde のようなブレース展開 • ENV=param commandで、command実行時のみENVを変える シェル芸の基礎:シェル機能 16
闇の魔術 :(){ :|:&; };: 絶対に実行してはいけない(cf. forkbomb) function colon() { colon
| colon& } colon 片方 (:&) がバックグラウンドプロセスになり、killできない プロセステーブルが飽和し、端末が死亡 閑話休題 シェル芸の基礎:シェル機能 17
シェル芸に関わる規範たち 18
UNIX哲学 一つのことを行い、またそれをうまくやるプログラムを書け。 協調して動くプログラムを書け。 標準入出力(テキスト・ストリーム)を扱うプログラムを書け。標準入出力 は普遍的インターフェースなのだ。 https://ja.wikipedia.org/wiki/UNIX哲学 シェル芸に関わる規範たち 19
POSIX • Portable Operating System Interfaces • https://pubs.opengroup.org/onlinepubs/9699919799/ • Xは?→
UNIXからきてる • C標準ライブラリやシェル(sh)の仕様が統一されている • 基本的なコマンド(Utilities)も載っている ◦ awk, cd, chmod, ls, sed, xargs, 他たくさん • 拡張シェル(bash, etc.)は(基本的に)これを守ってる • POSIXの仕様を守っている限りどの環境でも動くはず! シェル芸に関わる規範たち 20
sedとawkはPOSIX準拠 現在でも幅広くsedやawkが使われている理由の一つ (もちろんテキスト処理に特化しているというのもある) ただしGNU sed/awkなど独自拡張を行っているものもある • sed -r、sed -i、sed -y
• awkの各種強力な関数(丸投げ) 環境依存を気にするようになったら一歩沼に沈んだ証 シェル芸に関わる規範たち 21
GNU Coreutils 流石にPOSIXコマンドだけじゃ足りないことも多いので、 追加で存在を前提とされるコマンド群がある fmt, shuf, tee, seq, factorなど 一部コマンドは
POSIX にオプション拡張したものもある Coreutilsをさらに拡張したMoreutilsもある シェル芸に関わる規範たち 22
シェルでできる便利なコマンド 23
$ { time sleep 1 &>/dev/null; } 2>&1 | tail
-3 | awk '{print $2}' | xargs | tr ' ' , 0m1.052s,0m0.009s,0m0.021s # sleep 1を任意のコマンドに置き換えれば計測自動化できる # Bashのtimeコマンドの出力に依存している # for文や>>リダイレクトで複数条件計測とcsv錬成ができる シェルでできる便利なコマンド 24 $ time sleep 1 <空行> real 0m1.052s user 0m0.009s sys 0m0.021s | tail -3 | awk... 0m1.052s 0m0.009s 0m0.021s | xargs 0m1.052s 0m0.009s 0m0.021s
$ $(pbpaste) | pbcopy # macos $ $(xsel -b) |
xsel -bi # Linux (X) # Clipboardのコマンドを実行した結果をClipboardに入れる pbcopy/pbpasteは標準で入っている xselはパッケージマネージャを通してインストール可能 シェルでできる便利なコマンド 25
CSI(Control Sequence Introducer) ESC(0x1b) [ のエスケープシーケンスを入力することで様々な端 末制御が可能となる 文字色・カーソル移動・文字削除・端末サイズ変更、etc. • sh
→ printf '\x1b[31mRED\x1b[m' • bash → echo -e '\x1b[31mRED\x1b[m' • zsh → echo '\x1b[31mRED\x1b[m' RED # 表示設定(m):前景色(30)が赤(1)になる=31m もっと直感的に指示したい場合はtputコマンドがある 26 シェルでできる便利なコマンド
シェル芸人御用達コマンド・イディオム 27
# 整形コマンドとしてのxargs $ seq 12 | xargs -n 3 1
2 3 4 5 6 7 8 9 10 11 12 # 通常xargsは標準入力を最後尾に配置してコマンド実行する $ ls | xargs tar cvf dir.tar # が、コマンドを書かないとただの整形コマンドと化す $ echo -e "many spaces \tand\ttabs\!\!" | xargs many spaces and tabs!! シェル芸人御用達コマンド・イディオム 28
# 任意箇所に埋め込むxargs $ ls | xargs -I{} echo "There is
{} here." There is Desktop here. There is Documents here. … # I(large i)オプションによって任意の場所に埋め込める # 直後に指定した文字列を置換する # 複数箇所指定も可能 シェル芸人御用達コマンド・イディオム 29
$ seq 10 | tr '\n' ' ' $ seq
10 | tr -d '\n' 1 2 3 4 5 6 7 8 9 10 # 改行をスペースに変換する 12345678910 # 改行を消滅させる # この方法は一番最後の改行(10\n)も対象なことに注意 シェル芸人御用達コマンド・イディオム 30
$ seq 10 | tee >(tac | xargs > rev.txt)
| xargs | tr ' ' + | bc 55 # cat rev.txt -> 10 9 8 7 6 5 4 3 2 1 # teeコマンドは本来ファイルと標準出力へsplitさせる # Process Substitutionによって2つのコマンドに渡せる # 並行処理なので両方とも標準出力に流すと大変 # 環境を気にしないのならpeeコマンド(moreutils)が便利 $ seq 10 | pee "tac | xargs > rev.txt" "xargs | tr ' ' + | bc" シェル芸人御用達コマンド・イディオム 31
$ echo Helloworld | grep -o . H e l
l o w o r l d # grepは基本的にマッチした行を抜き出す # -oはマッチした箇所のみを抜き出す # . は任意の1文字なので、全文字が分割表示される シェル芸人御用達コマンド・イディオム 32
$ yes 'echo $RANDOM' | head -3 | bash 28995
29287 23092 # コマンドを自力で生成してからpipe先のbashに投げて実行 # 複雑なコマンドを生成するもよし、 # ランダム要素のあるコマンドを何回も実行するときも便利 # seqをパイプすればfor文より見た目がエレガント[要出典] シェル芸人御用達コマンド・イディオム 33
$ shuf -ren10 {大,中,小,末,}吉 {大,}凶 # おみくじ10連打 • -r 再抽選可
• -e 標準入力ではなく引数をシャッフル • -n10 10回出力 # Q. 本当に御用達なんですか? # A. 他に書くとこがなかった シェル芸人御用達コマンド・イディオム 34
$ sudo cat /var/log/auth.log | grep "Invalid user" | cut
-f9 -d' ' | sort | uniq -c | sort -nr | head -10 # ssh不正ログインしてこようとしたusernameを暴く # Ubuntu 18.04で動作した # sort | uniq -c | sort -nr は最頻ランキングを作るのに便利 # cut -fnum -d' ' はスペースで区切られたnum番目を取得 シェル芸人御用達コマンド・イディオム 35
難読化 36
$ $(echo d)$’\x61’$(echo dGUK | base64 -d) Mon Mar 9
09:46:30 JST 2020 # それぞれ展開すると “date” になる # シェルは展開できるものを全て展開した後に解釈する • echo d → d • $'\x61' → a • echo dGUK | base64 -d → te 難読化 37
難読化テクニックたち echo $[] → 0 ($[]は算術演算、何もないと0) echo ${##} → 1
($#:引数の数=0、${#var}:文字列長) $(: shutdown -h now) (一瞬ひりつかせるが何もしない) /???/???/???1??? (/usr/bin/sha1sumを呼ぶ、環境依存) cut -c n (標準入力のn文字目を取り出す。切り貼りする) 難読化 38
ところで Connpassページのシェル芸、Bashで実行できます $ pbpaste | bash ShellGei!! 難読化 39
どういうこと $ pbpaste | bash -x でデバッグできる ___=$(.&>/???/??/${##}); ___に .
&>/dev/fd/1 の出力を代入する .コマンドがエラーを返すので、それをfd1にリダイレクト -bash: .: ファイル名が引数として必要です .: 使用法: . filename [arguments] __=$? __に$?(直前コマンドの終了ステータス=2)を代入 難読化 40
つづき ! ___=${___##*.} ___に、___の最後の.以降の文字列を代入 -bash: .: ファイル名が引数として必要です .: 使用法: .
filename [arguments] 言語環境に依存しない部分を抽出(このメッセージ自体はBashの builtinなので、Bashで実行している限り変わらない) 難読化 41
つづき ____=$(${___:$(($__$#-$?)):$?}${___:$__*$__:$?}${___:$ (($__$#-$__)):$?} -${___:$(($__#$?$?$#$?)):$?}&>/???/??/$?) 先ほどのコマンドで!をつけたので、$?が反転して1になる $#は0、これらで$___=' filename[arguments]'を切り貼り ____=$(set -g &>/dev/fd/1)
bash: 1 行: set: -g: 無効なオプションです set: 使用法: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...] 難読化 42
つづき これらを繰り返して最終的に ___=(eval $(echo {a..\u7a})) ___=(a b c d e
… x y z) # ___はarrayになる を取得 配列インデックスをいじって任意コマンドが実行できる 難読化 43
さいごに 44
シェル芸勉強会 • 2ヶ月に1回新宿で開催される勉強会 • 界隈がfreakyで面白い(沼にハマった人たちを参考) • シェルのワンライナーという制約下で8問解く 例えば: 日経のページから日経平均株価の日次データをダウンロードし て、毎月の終値の最高値と最安値を出力してください。
https://b.ueda.tech/?post=20191228_shellgei_45#q2 勉強会リンク(https://usptomo.doorkeeper.jp/) 45 さいごに