- 投稿日:2020-07-01T23:17:46+09:00
「UNIXという考え方―その設計思想と哲学」を読んだ
0. はじめに
こんにちは。都内でエンジニアをしている、@gkzvoiceです。
先日、Twitterのタイムラインに@nukumaro22さんからこんな投稿が流れてきました。これは哲学書です pic.twitter.com/4lMKQtOuAV
— iberianpig(Kohei Yamada) (@nukumaro22) June 4, 2020というわけで、早速、Amazonでポチり、読んでみました。
本書を読んで、覚え書きをしていたので、インターネットに放流したいと思います。
書評っぽい内容ですが、タイトルに書評と付け忘れました。。【コマンドの結果をカラとする設計とless is moreの精神】
— gakuji tamaki@July Tech Festa 2020運営スタッフ (@gkzvoice) June 30, 2020
lsコマンドの結果、該当ファイルがなければ、"not found"と表示するべきかもしれない。
しかし、その結果を別のコマンドに渡すとなると出力結果はファイル名かカラのほうが処理が単純といえる。
『UNIXという考え方』#夏の読書感想文 pic.twitter.com/qGqtdQUIbC1. 本書の目次
- 第1章 UNIXの考え方:たくさんの登場人物たち
- 第2章 人類にとっての小さな一歩
- 第3章 楽しみと実益をかねた早めの試作
- 第4章 移植性の優先順位
- 第5章 これこそ梃子の効果!
- 第6章 対話的プログラムの危険性
- 第7章 さらなる10のUNIXの考え方
- 第8章 一つのことをうまくやろう
- 第9章 UNIXとその他のオペレーティングシステムの考え方
2. 本書のおすすめポイント
- 内容が全く古臭くない
- 2001年初版発行、私が読んだものは2008年第14刷発行と10年以上前に書かれたもの。
- 中身は特定の技術にフォーカスしたものではない。
- むしろ
「哲学的」
なお話。- 時代が変われど変わらない考え方を取り上げているせいか、UNIXの思想は、
マイクロサービスの思想
やザッカーバーグ氏のあまりに有名な言葉の「Done is better than perfect.」
に通じる。- 空き時間に読めるほどのコンパクトさ
- 仕事や勉強の箸休めに読むのもいいかもしれない。
3. 読んで印象に残ったこと
3-1.コマンドの結果をカラとするのには理由がある
- lsコマンドの結果、該当ファイルがなければ、コマンドの実行者に該当ファイルが存在しないことを"not found"などと伝えるようにするべきかもしれない
- しかし、その結果を別のコマンドに渡すとなると出力結果はファイル名かカラのほうが処理が単純となる。
- lsコマンドの使い勝手という面では`一見配慮に欠けた実装(該当ファイルがあれば出力し、なければ出力しない)のほうが開発者にとって都合がいい。
3-2.Worse is better.
- UNIXの思想のひとつ
- いまいちピンときていなかったが、@t_wadaさんのTweetを拝見して腑に落ちた
Worse Is Better に関する自分の解釈は「設計の正しさ/美しさと実装の単純さが対立する(両立できない)ときは、実装の単純さを選択した方が、たとえそれが漏れのある抽象になったとしても現実の問題を解決し、実装の単純さによって開発参加のハードルが下がり、進化的な強さを獲得できる」というもの
— Takuto Wada (@t_wada) April 6, 2018
- 自分の言葉で説明すると、こんな具合
- 複雑性は増すけどよりよい設計と、それらは劣るけど単純な設計のうち、後者を選択すると、コントリビュートの敷居を下げ、長い目で見ると前者より優れたものとなる。
3-3.Worse is betterの先にあるもの
- 本書では、Worse is betterについて、このように続けている。
「良くなる」ためには、単純さを犠牲にして完全性を追求しなければならない。そうなるとUNIXはもはやUNIXではなくなる。
一見自己矛盾を抱えているように思えるけど、
「良くなったUNIX」は非連続的な発展を遂げ、別次元のworse is betterなもの
であってほしいと思った。Linuxカーネルは肥大化しているとは実際どういうことなのか分かっていないけど、Linuxカーネルの肥大化はその一例かも
3-4.本書の話題から外れるけどLinuxカーネルのメンテナーの仕事内容
- @komi_edtr_1230さんの投稿を拝見してLinuxカーネルのメンテナーの仕事の内容が気になった
- これは宿題
Linuxカーネルのコアのメンテナーの多くは50代や60代で、これからLinuxも次の世代へと引き継いでいく必要があり、その中でひょっとしたらLinuxカーネルがCではなくRustのような別の言語で書かれる可能性もあるし、何かしらの変化が起こるかも、と。 https://t.co/TvvFoIFvMJ
— コミさん (@komi_edtr_1230) July 1, 2020P.S. Twitterもやってるのでフォローしていただけると泣いて喜びます:)
- 投稿日:2020-07-01T23:10:46+09:00
ubuntu: マウス・タッチパッドの入力軸を回転
terminalで以下を実行
左90度回転xinput set-prop 13 'Coordinate Transformation Matrix' 0 -1 0 1 0 0 0 0 1 xrandr -o left右90度回転xinput set-prop 13 'Coordinate Transformation Matrix' 0 1 0 -1 0 0 0 0 1 xrandr -o right180度回転xinput set-prop 13 'Coordinate Transformation Matrix' -1 0 0 0 -1 0 0 0 1 xrandr -o inverted0度に戻すxinput set-prop 13 'Coordinate Transformation Matrix' 1 0 0 0 1 0 0 0 1 xrandr -o normal上記コマンド中
13
は各端末のデバイスidに書き換える。
デバイスidは、以下のように、xinput
コマンドで確認可能。kinomi@pop-os:xinput ⎡ Virtual core pointer id=2 [master pointer (3)] ⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)] ⎜ ↳ SynPS/2 Synaptics TouchPad id=13 [slave pointer (2)] ⎣ Virtual core keyboard id=3 [master keyboard (2)] ↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)] ↳ Power Button id=6 [slave keyboard (3)] ↳ Video Bus id=7 [slave keyboard (3)] ↳ Power Button id=8 [slave keyboard (3)] ↳ Sleep Button id=9 [slave keyboard (3)] ↳ Topre Corporation HHKB Professional id=10 [slave keyboard (3)] ↳ HD Webcam: HD Webcam id=11 [slave keyboard (3)] ↳ MSI WMI hotkeys id=14 [slave keyboard (3)] ↳ AT Translated Set 2 keyboard id=12 [slave keyboard (3)]
任意の角度に回転
1 0 0 0 1 0 0 0 1
部分を書き換える
これは行列を表す
回転角度0の場合
| 1 0 0 |
| 0 1 0 |
| 0 0 1 |反時計回りにθ回転の場合は、
| cosθ -sinθ 0 |
| sinθ cosθ 0 |
| 0 0 1 |
cos -sin 0 sin cos 0 0 0 1
に書き換える関連する数学
- 投稿日:2020-07-01T17:52:25+09:00
macOSでクリップボードにある文章の文字数を数える
背景
- 文字数をカウントしてくれるwebサービスを使うことがあった.
- でもいちいちブラウザに切り替えてコピペして文字数みてまた書き直して…という作業がめんどくさい.
- MS Word とかいう邪悪なソフト使いたくない.
- 文章の一部をいちいち別のファイルにコピペして
wc
コマンド叩くのもめんどくさい.- Neovim で文章を書くことが多いからターミナルだけで作業を完結させたい.
- 具体的にはこれと同じ機能をターミナルだけでやりたい
方法
pbpaste | wc -m解説
pbpaste
: クリップボードのデータを標準出力する.テキストならテキストが出力される. Finder でファイルをコピーしたならファイル名が出力される.wc -m
: 文字数を数えてくれる.-m
オプションでマルチバイト文字にも対応してくれる.- パイプを使って
pbpaste
の出力をwc -m
の入力として受け取り,最終的にwc -m
の結果を出力する.応用例
行数も含めた文字数を数えたい
-l
オプションを追加します.pbpaste | wc -ml2個の数値が出力されるようになり,1個目が行数,2個目が文字数に対応します.
改行を削除した文字数を数えたい
tr
コマンドで改行文字を削除します.pbpaste | tr -d '\n' | wc -m改行と空白を削除した文字数を数えたい
tr
コマンドで空白と改行文字を削除します.pbpaste | tr -d '\n' | tr -d ' ' | wc -m他の文字コードにエンコードして文字数を数えたい
適当なオプションを付けて
nkf
コマンドを間に挟みます.ISO-2022-JP
pbpaste | nkf -j | wc -mShift_JIS
pbpaste | nkf -s | wc -mEUC-JP
pbpaste | nkf -e | wc -mUTF-16
pbpaste | nkf -w16 | wc -m参考文献
- 投稿日:2020-07-01T17:13:02+09:00
WSL 上で同一ディストリビューションの環境を複数インストール・管理する
Microsoft Storeから WSL 環境をインストールすると、1種類のディストリビューションは1個の環境としてしかインストールできない(と思う)。
だが同一ディストロの環境を気軽に複数作ったり壊したり消したり、使い捨てで使いたいこともあるだろう。ターミナルから簡単に環境を複製できるのでやり方を書いておく。手順
WSL が入っているのは前提とする。まずターミナルで
wsl -l --verbose
を実行して、手元に存在する環境を確認する。PS C:\Users\user01> wsl -l --verbose NAME STATE VERSION * Ubuntu-20.04 Running 2 docker-desktop Running 2 docker-desktop-data Running 2例えばストアからインストールした Ubuntu-20.04 が入っていれば上記のように出力される。この、環境名
Ubuntu-20.04
としてインストールされている Ubuntu を使い捨て用に複製してみることにする。WSL のエクスポート機能で、環境を丸ごと tar ファイルとして出力できる。
wsl --export (エクスポートしたい WSL 環境名) (出力ファイル名)
を実行すればよい。PS C:\Users\user01\export_distro> wsl --export Ubuntu-20.04 FocalFossa_copy.tarこれで元の
Ubuntu-20.04
の環境が tar ファイルとして出力されるので、あとはこれに別の環境名を付けてインポートすれば同一環境が得られる。wsl --import (WSL 下に登録する環境名) (インストール先パス) (インポートする環境.tar)
を実行すればよい。PS C:\Users\user01\export_distro> wsl --import FocalFossa_copy ..\wsl_manual_install\ FocalFossa_copy.tarこれで、指定した環境名で元の
Ubuntu-20.04
と同一の環境が複製された。PS C:\Users\user01> wsl -l --verbose NAME STATE VERSION * Ubuntu-20.04 Running 2 FocalFossa_copy Stopped 2 docker-desktop Running 2 docker-desktop-data Running 2ターミナルから
wsl -d (環境名)
と打ち込んで起動してもよいし、もしくは Windows Terminal のタイトルバーの∨
ボタンから表示できる環境リストから選んで起動するなりすればよい。
PS C:\Users\user01> wsl -l --verbose NAME STATE VERSION * Ubuntu-20.04 Running 2 FocalFossa_copy Running 2 docker-desktop Running 2 docker-desktop-data Running 2無事、同一ディストロが別名環境として起動している。
なお、インポート時に指定したインストール先に環境の実体であるハードディスクイメージファイル
ext4.vhdx
が生成されているが、中身は\\wsl$\
下にマウントされているのでそちらからエクスプローラーでブラウジングすることができる。
いらなくなった環境を削除したいときは、wsl --unregister (登録名)
で削除できる。わりと簡単に環境を複製・破壊・廃棄できるので、気兼ねなく遊んでみよう!
- 投稿日:2020-07-01T16:02:20+09:00
故障対応の原因切り分けで知っておきたいコマンド集(サーバ編)
システム系コマンド
Linux稼働時間を表示(uptime)
Linuxの稼働時間を表示する。ping疎通が一時的にNGになった際等に、サーバが再起動が走ったことを疑い、確認することがある。
$ uptime 12:16:05 up 48 days, 17:53, 2 users, load average: 0.00, 0.02, 0.00なお、ロードアベレージはCPUのコア数よりも低い値であることが望ましい。
プロセス状態の確認(topコマンド,psコマンド)
(スナップショット的に)実行中のプロセス状態を一覧表示する
(スナップショット的に)実行中のプロセス状態を一覧表示する場合は、psコマンドを使用する。「どのプロセスで高負荷になっているのか?」等の確認で使用する。
$ ps aux
なお、特定サービスのプロセス状況を確認するために、grepコマンドと組み合わせて使用する場合がある。下記は、Nginxのプロセス状況を確認した例である。
$ ps aux | grep -e nginx -e %CPU(リアルタイムの)実行中のプロセスを一覧表示する
(リアルタイムの)実行中のプロセス状態を一覧表示する場合は、topコマンドを使用する。なお、オプションに「-c」を付けることで、コマンドをフルパス表示できるため、おすすめである。PSコマンド同様に「どのプロセスで高負荷になっているのか?」等の確認で使用する。
$ top -cなお、下記のようにpsコマンドでプロセスIDを確認し、「-p」オプションを指定することで、特定のプロセス状況だけを確認することができる。下記は、Nginxのプロセス状況を確認した例である。
$ ps aux | grep -e nginx -e %CPU USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2142 0.0 0.0 53788 68 ? Ss Jun06 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf nginx 2143 0.0 0.1 85396 3048 ? S Jun06 0:03 nginx: worker process root 13439 0.0 0.0 12108 1088 pts/0 S+ 16:53 0:00 grep --color=auto -e nginx -e %CPU // nginxのプロセスIDを指定して実行する $ top -cp 2142 top - 16:54:05 up 36 days, 22:31, 1 user, load average: 0.06, 0.23, 0.16 Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 1829.2 total, 80.2 free, 1558.7 used, 190.4 buff/cache MiB Swap: 2048.0 total, 854.2 free, 1193.8 used. 120.1 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2142 root 20 0 53788 68 68 S 0.0 0.0 0:00.01 nginx出力結果の見方
1行目:uptime(起動時間)と全体的な負荷の情報が出力されている。
top - 16:45:36 up 36 days, 22:23, 1 user, load average: 0.01, 0.02, 0.002~3行目:CPUとタスクに関する状況が出力されている。
Tasks: 116 total, 1 running, 115 sleeping, 0 stopped, 0 zombie %Cpu(s): 12.5 us, 0.0 sy, 0.0 ni, 87.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st4~5行目:メモリとスワップに関する状況が出力されている。
MiB Mem : 1829.2 total, 74.0 free, 1558.9 used, 196.3 buff/cache MiB Swap: 2048.0 total, 854.2 free, 1193.8 used. 119.9 avail MemCPU、メモリ、ディスクI/Oの統計情報を確認(vmstat)
仮想メモリやCPU、ディスクI/Oの統計情報を表示する。「--unit」オプションでmを指定することで、MB表示になり見やすくなる。
$ vmstat --unit m procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 153 228 115 962 0 0 234 16 3 3 1 0 99 0 0なお、引数に「1」を指定することで1秒間隔で表示することができる。
$ vmstat --unit m 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 153 228 115 962 0 0 234 16 3 3 1 0 99 0 0 0 0 153 227 115 962 0 0 0 0 150 168 0 0 100 0 0 0 0 153 227 115 962 0 0 0 0 151 188 0 0 100 0 0CPU、ディスクI/Oの統計情報を確認(iostat)
CPUの使用率とI/Oデバイスの利用状況を表示する。
$ iostat -h Linux 4.18.0-147.8.1.el8_1.x86_64 (XXX-XX-XX-XXX) 07/01/2020 _x86_64_ (3 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 0.6% 0.0% 0.4% 0.0% 0.0% 98.9% tps kB_read/s kB_wrtn/s kB_read kB_wrtn Device 11.96 700.4k 48.5k 2.7T 194.7G vda 0.00 0.0k 0.0k 416.0k 0.0k scd0メモリ利用状況の確認(freeコマンド)
メモリの利用状況を表示する。
// キロバイト単位で参照する $ free // メガバイト単位で参照する $ free -m // ギガバイト単位で参照する $ free -gディスク利用状況の確認(dfコマンド)
ディスクの利用状況を表示する。なお、「-h」オプションを指定することで、適切な単位をつけて表示してくれるため、おすすめである。
$ df -h(特定ディレクトリの)ディスク利用状況の確認(duコマンド)
(特定ディレクトリ配下の)ディスク利用状況を表示する。なお、「-h」オプションを指定することで、適切な単位をつけて表示してくれるため、おすすめである。
$ du -h | sort -hrまた、「--max-depth」オプションを指定することで、どの深度まで確認するかを指定することができる。下記はカレントディレクトリ内のディスク利用状況を確認する例である。
$ du --max-depth=1 -h | sort -hr 772M . 743M ./.vscode-server 13M ./.local 11M ./.cache 44K ./.vscode-remote 8.0K ./.vscode 8.0K ./.ssh 8.0K ./.pylint.d 8.0K ./.configボリュームのマウント状況を確認(mountコマンド)
ボリュームのマウント状況を確認する。「データが読み込めない時」等に、ディスクが正しくマウントされているか確認する際に使用する。なお、「-l」オプションを付けずに実行すると、マウントするべきでないディスクまでマウントしてしまう可能性があるため、実行時には注意が必要である。ただ状況を確認するだけの場合は、「-l」オプションを付けることを心がけましょう。
$ mount -lまた、mountコマンドと関連性が深いファイルに「/etc/fstab」があります。これは、サーバ起動時やシステムマネージャが再読み込みされた際に、反映するボリュームのマウント設定内容が記述されています。fstabにマウントの設定が記述されているのにも関わらず、上記の「mount -l」コマンドでマウント状態が確認できない場合は、異常を疑う余地があります。
$ cat /etc/fstabLinuxカーネルが出力したメッセージを確認(dmesg)
Linuxカーネル(プロセス管理、メモリ管理、スケジュール管理等のOSの中核機能を担うソフトウェア)が出力した情報を確認する。なお、「-T」オプションを指定することで、時刻情報が見やすくなる。また、「-x」オプションを指定することで、メッセージの情報レベルを表示してくれる。サーバを再起動したが、アプリケーションがデータを正常に読み込めない際等に、dmesgの出力を確認するとディスクが破損している等を見つけれる場合がある。
$ dmesg -Tx過去のリソース利用傾向を確認(sar)
過去のリソース(CPU,メモリ等)の利用傾向を確認する。なお、サーバによってはインストールされていないことがあるため、注意が必要である。
// 過去のCPU利用傾向を確認する $ sar -u // 過去のメモリ利用傾向を確認する $ sar -rネットワーク系コマンド
ネットワークの疎通を確認(ping)
ネットワークの疎通を確認する。ちなみに、IPアドレス「8.8.8.8」はGoogleのPublicDNSを示している。pingの疎通チェックがNGの場合は、次に紹介する「traceroute」コマンドを利用して、どこで疎通NGとなったのかを確認すると良いだろう。
// IPアドレスで疎通を確認する $ ping 8.8.8.8 // ホスト名で疎通を確認する ※名前解決もしてくれる $ ping google.com // 1秒間隔で疎通を確認し続ける $ ping -i 1 8.8.8.8 // IPv4で疎通を確認する $ ping -4 google.com // IPv6で疎通を確認する $ ping -6 google.comネットワークの経路を確認(traceroute)
ネットワークの経路を確認する。なお、サーバによってはインストールされていないことがあるため、注意が必要である。どこで疎通NGとなったのかを確認する際に使用することが多い。
$ traceroute 8.8.8.8
名前解決を確認(nslookup,dig)
名前解決を確認する。nslookupとdigコマンドの違いは、前者はネームサーバの応答結果を見やすく加工してくれるのに対して、後者はネームサーバの応答結果をそのまま表示する。DNSが疑わしい場合は、まずこのコマンドを使用して、名前解決の正常性を確認すると良いだろう。
// 正引きを確認する $ nslookup google.com // 逆引きを確認する $ nslookup 8.8.8.8// 正引きを確認する $ dig google.com // 逆引きを確認する $ dig -x 8.8.8.8TCPソケットの接続状況を確認(ss,netstat)
TCPソケットの接続状況を確認する。なお、netstatはRHEL7以降では非推奨となっており、代替コマンドとしてssが推奨されている。以下は、IPv4のTCPソケットの接続状況を確認するコマンドである。ポートの使用状況から、どんなサーバが動作しているのかを確認することに利用したりする。なお、非推奨ではあるがnetstatの方が出力が見やすいため、完全に利用できなくなるまではssコマンドよりも、netstatコマンドを使用すると良いだろう。
// 推奨 $ ss -at4 // 非推奨 $ netstat -at4ネットワークの状況の確認(ip,ifconfig)
ネットワークの状況を確認する。なお、ifconfigはRHEL7以降では非推奨となっており、代替コマンドとしてipが推奨されている。以下は、存在するインターフェースごとのネットワーク設定を表示するコマンドである。ネットワークインターフェースのリンクアップ状況の確認等に使用する。
// 推奨 $ ip a // 非推奨 $ ifconfig -aルーティングテーブルの確認(ip,route,netstat)
ルーティングテーブルを確認する。なお、routeはRHEL7以降では非推奨となっており、代替コマンドとしてipが推奨されている。以下は、ルーティングテーブルを確認するコマンドである。非推奨ではあるが、routeコマンドの出力の方が見やすいため、完全に利用できなくなるまではipコマンドよりも、routeコマンドを使用すると良いだろう。
// 推奨 $ ip r // 非推奨 $ route // 非推奨 $ netstat -nrARPキャッシュテーブルを確認
ARPキャッシュテーブルを確認する。なお、arpはRHEL7以降では非推奨となっており、代替コマンドとしてipが推奨されている。以下は、ARPキャッシュテーブルを確認するコマンドである。一例だが、ルータを交換した際等に、APRキャッシュに前の機器のMACアドレスが残置してしまい、通信障害が発生する場合等があり、その際の切り分けとして使用する。
// 推奨 $ ip n // 非推奨 $ arp -aその他
ログをリアルタイムで確認
出力されるログをリアルタイムで確認する。現在進行形でトラブルが発生している場合に、どんなログが出力されているのかを確認することに有効である。
$ tail -f access.logなお、膨大なログが短時間で出力されるような場合は、grepコマンドと組み合わせて使用することも多い。下記はtailコマンドとgrepコマンドを組み合わせて、404エラーのみを標準出力した例である。
$ tail -f access.log | grep 404 125.197.158.68 - - [01/Jul/2020:13:45:11 +0900] "GET /404 HTTP/1.1" 301 162 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36" "-" 125.197.158.68 - - [01/Jul/2020:13:45:11 +0900] "GET /404 HTTP/2.0" 404 548 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36" "-" 125.197.158.68 - - [01/Jul/2020:13:45:11 +0900] "GET /favicon.ico HTTP/2.0" 404 548 "https://example.com/404" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36" "-"(様々な)条件にマッチするファイルを検索
(様々な)条件にマッチするファイルを検索する。ディレクトリ・ファイル構成が把握できておらず、探しているファイルがどこにあるかわからない場合がよくあります。そんな際に、本コマンドを使用して検索することが多い。
// 検索パス配下で、指定したファイルを検索する $ find 検索パス -name ファイル名 // 実行例 $ find /var/log/ -name "access.log" /var/log/nginx/access.log // ワイルドカードを使用した例 $ find /var/log/ -name "*.log" /var/log/letsencrypt/letsencrypt.log /var/log/dnf.rpm.log /var/log/dnf.librepo.log /var/log/boot.log /var/log/nginx/error.log /var/log/nginx/access.log /var/log/audit/audit.log /var/log/cloud-init-output.log /var/log/cloud-init.log /var/log/dnf.log /var/log/sssd/sssd_nss.log /var/log/sssd/sssd_implicit_files.log /var/log/sssd/sssd.log /var/log/hawkey.log /var/log/tuned/tuned.log // ファイル種別(ファイルのみ)を指定した例 $ find /opt/docker/ -name "*.conf" -type f /opt/docker/nginx/conf/default.conf /opt/docker/nginx/conf/nginx.conf // ファイル種別(ディレクトリのみ)を指定した例 $ find /opt/docker/ -name "nginx" -type d /opt/docker/nginxファイル内から特定の文字を含む行を抽出
ファイル内から特定の文字を含む行を抽出する。とても頻繁に利用するコマンドであるが、故障対応においてはログからエラーが出力されているかを確認するために、使用したりすることが多い。ここでは、個人的に使用する例を紹介したいと思う。
// 指定したファイル内から特定の文字を含む行を抽出 $ grep access.log nginx.conf access_log /var/log/nginx/access.log main; // ワイルドカードを使用してファイル群から特定の文字を含む行を抽出 $ grep http *.conf default.conf: return 301 https://$host$request_uri; default.conf: listen 443 ssl http2; default.conf: listen [::]:443 ssl http2; default.conf: proxy_pass http://localhost:5601; nginx.conf:http { nginx.conf: '$status $body_bytes_sent "$http_referer" ' nginx.conf: '"$http_user_agent" "$http_x_forwarded_for"'; // -vオプションで特定の文字列だけ抽出から除外する $ echo -e "test\ntast\ntest" > test.txt $ cat test.txt test tast test $ grep test test.txt test test $ grep -v test test.txt tast // -eオプションでOR検索で特定の文字列を抽出する $ grep -e test -e tast test.txt test tast test // -iオプションで大文字と小文字を区別せずに抽出 $ grep Access.log nginx.conf $ grep -i Access.log nginx.conf access_log /var/log/nginx/access.log main; // サブディレクトリも含めて検索を実行し、シンボリックリンクの先も対象とする $ grep -R http nginx/conf/default.conf: return 301 https://$host$request_uri; nginx/conf/default.conf: listen 443 ssl http2; nginx/conf/default.conf: listen [::]:443 ssl http2; nginx/conf/default.conf: proxy_pass http://localhost:5601; nginx/conf/nginx.conf:http { nginx/conf/nginx.conf: '$status $body_bytes_sent "$http_referer" ' nginx/conf/nginx.conf: '"$http_user_agent" "$http_x_forwarded_for"'; nginx/html/index.html:<a href="http://nginx.org/">nginx.org</a>.<br/> nginx/html/index.html:<a href="http://nginx.com/">nginx.com</a>.</p>ファイルを一覧表示
ファイルを一覧表示する。ここでは、個人的に使用する例を紹介したいと思う。
// シンプルにファイルを一覧表示 $ ls conf docker-compose.yml html // ファイル情報も表示 $ ls -l total 12 drwxr-xr-x 2 root root 4096 May 22 20:52 conf -rw-r--r-- 1 root root 655 May 22 20:37 docker-compose.yml drwxr-xr-x 2 root root 4096 May 20 16:02 html // ドットファイルも表示 $ ls -la total 20 drwxr-xr-x 4 root root 4096 May 22 20:37 . drwxr-xr-x 5 root root 4096 May 19 13:47 .. drwxr-xr-x 2 root root 4096 May 22 20:52 conf -rw-r--r-- 1 root root 655 May 22 20:37 docker-compose.yml drwxr-xr-x 2 root root 4096 May 20 16:02 html // ファイルの更新日が新しい順にリストし、その並びを逆順に表示する $ ls -latr total 20 drwxr-xr-x 5 root root 4096 May 19 13:47 .. drwxr-xr-x 2 root root 4096 May 20 16:02 html -rw-r--r-- 1 root root 655 May 22 20:37 docker-compose.yml drwxr-xr-x 4 root root 4096 May 22 20:37 . drwxr-xr-x 2 root root 4096 May 22 20:52 conf // ファイルサイズを人が読みやすい形式で表示する $ ls -latrh total 20K drwxr-xr-x 5 root root 4.0K May 19 13:47 .. drwxr-xr-x 2 root root 4.0K May 20 16:02 html -rw-r--r-- 1 root root 655 May 22 20:37 docker-compose.yml drwxr-xr-x 4 root root 4.0K May 22 20:37 . drwxr-xr-x 2 root root 4.0K May 22 20:52 conf // 再帰的に表示する # ls -latrhR .: total 20K drwxr-xr-x 5 root root 4.0K May 19 13:47 .. drwxr-xr-x 2 root root 4.0K May 20 16:02 html -rw-r--r-- 1 root root 655 May 22 20:37 docker-compose.yml drwxr-xr-x 4 root root 4.0K May 22 20:37 . drwxr-xr-x 2 root root 4.0K May 22 20:52 conf ./html: total 16K -rw-r--r-- 1 root root 612 Apr 14 23:19 index.html -rw-r--r-- 1 root root 494 Apr 14 23:19 50x.html drwxr-xr-x 2 root root 4.0K May 20 16:02 . drwxr-xr-x 4 root root 4.0K May 22 20:37 .. ./conf: total 16K -rw-r--r-- 1 root root 670 May 20 19:32 nginx.conf drwxr-xr-x 4 root root 4.0K May 22 20:37 .. -rw-r--r-- 1 root root 1.3K May 22 20:52 default.conf drwxr-xr-x 2 root root 4.0K May 22 20:52 .テキストをスクロール表示
テキストを表示する。ログからエラーの箇所を重点的にチェックする時等に使用する。
$ more access.log
$ less access.log
$ view access.log
「more」「less」「view」コマンドの違い
細かな違いはあるが、知っておきたい違いを以下の表にまとめています。
コマンド 表示の速さ 終了方法 more 速い 行末まで行くと自動終了 / q / Ctrl+C less 速い q view 遅い :q
- 投稿日:2020-07-01T13:53:17+09:00
IT技術界のレジェンドを知りたい
皆さんが知っているIT技術界の「スゴイ人」を教えて頂けないでしょうか!!!orz
はじめに
本記事に技術情報は一切ありませんし、誰か教えて!っていう大変他人任せで低レベルな記事です。タイトルからわかるかと思いますが、適当にタグをつけております。すみませんがご了承ください。
不快な方はスルー推奨です。また後日、教えてもらった技術者を調べてみて、特に気になった方2,3人を再度記事にしてみたいなと思っております。(私なんかの文章読みたい人なんていないと思いますが、教えて頂いた方への感謝・尊敬の念を込めて。)
レジェンド(憧れの存在)がもたらす効果
どんな業界でもレジェンドの存在は憧れ、希望を生み、業界全体のレベルアップに繋がると思います。
私が好きなバスケ界では、マイケルジョーダン、マジックジョンソン、ラリーバードなどなど多くのレジェンドたちの存在がありました。
私の学生時代はアイバーソン、コービー、ナッシュ、シャックなどなどのスーパースターがNBAを引っ張っていました。ジェイソンウィリアムズの肘パスは誰もが一度練習したでしょう。(笑)
そうです。普段のモチベーションに「憧れ」は必要だと思うんです!!!私は知らない!(ドン!!!)
私は大卒後、社会人からエンジニアになり今年で5年目になります。(早いなー)
学生時代は全くITに興味がありませんでした。そのためスゴイ技術者・経営者を全く知りません。orz
Appleのスティーブジョブズ&ウォズニアックコンビ、Microsoftのビル・ゲイツ、facebookのザッカーバーグ、Googleのラリー・ペイジ、Amazonのジェフ・ベゾス、Oracleのラリーエリソンくらいなら(名前だけ)もちろん知っています。そしてそして、日本人技術者の名前を本当に知りません!!
これは実際悲しいことですが、若手技術者の多くはそんなもんじゃないでしょうか。
私が知っているのは堀江貴文さん、西村ひろゆきさん、つくばの落合さん等メディアに出ている人たちくらいです。(本当はもう少し知っています。)おすすめのレジェンド教えてください
私はIT業界は少数の天才たちによって支えられているんじゃないかと思っています。知らんけど。
そこで!日本のIT系技術者・経営者で(もちろん外国の方でも嬉しいです。)おススメのレジェンドの方を教えて頂けないでしょうか。またはこんなすごいことが現在進行形で行われている。などなど
(インフラ技術開発者・ソフトウェア開発者・OSS開発者・言語開発者・伝説的な経営者)この人はこんな方だ!というコメントもあればぜひ調べ、書籍もあったら読んでみます。
私のこれからのエンジニア人生のため、皆さんのモチベーションを高めるために!orz
※ある程度調べれば出てくる人でないと情報ゲットできないので調べれば出てくる方でお願い致します。
好奇心を満たしたいだけなので何卒お気軽に。。「IT業界」と、本当にざっくりしていて恐縮ですが よろしくお願い致します。
- 投稿日:2020-07-01T13:32:21+09:00
curl でDBやキャッシュの疎通確認もできる
これは何
DBへのネットワーク的な疎通確認といえば、MySQLだったら mysql-client、Redisならredis-cliなど専用のコマンドが一般的ですが、単にネットワーク的に疎通を確認したいということであれば curl だけでもできます。
コマンドイメージ
$ curl -v telnet://hogehoge.com:3306疎通確認をする一般的なコマンドといえば
- ping コマンド
- メリット: だいたいどんなサーバにも入っている(気がする)
- デメリット:
- icmp を通していないサーバの確認には使えないし、pingだけの確認だと実際には到達できていてもサーバに到達していないと勘違いを起こしやすい
- トランスポート層のポートまで確認できない
- telnet コマンド
- メリット: ホスト名とポートを指定できる柔軟なコマンド
- デメリット: 接続を解除する方法がわかりにくかったりしてやや使いづらい
- curl コマンド
- 一般的に http や https での接続確認
- 使いやすい
よくある curl の使い方(httpやhttpsに対する疎通確認)
$ curl -v https://hogehoge.comのように http や https プロトコルを使って接続。
プロトコルをつけなかった時にはどうなるのか?
ubuntuで$ man curl
をすると以下のような記述がありました。If you specify URL without protocol:// prefix, curl will attempt to guess what protocol you might want. It will then default to HTTP but try other protocols based on often-used host name prefixes. For example, for host names starting with "ftp." curl will assume you want to speak FTP.プロトコルをつけないと、よく使われるスキーマが適当に試されるようです。
例えばローカルに立っているサーバに対してプロトコルを指定せずにlocalhostに対して叩くと、httpだと解釈されて実行されます。
$ curl -I localhost HTTP/1.1 404 Not Found Server: nginx Content-Type: text/html; charset=UTF-8 Connection: keep-alive X-Powered-By: PHP/7.2.0RC6 Cache-Control: no-cache, private date: Tue, 30 Jun 2020 09:27:28 GMTDBやキャッシュへの接続確認
とあるサーバ(ubuntu)からあるDBサーバに接続確認したいケースは以下のようになります。
telnetプロトコルを使用してポートを指定します。telnetはコマンド名だと思っていましたが、実際にはtelnetプロトコルというのがあるようでした。
参考: https://ja.wikipedia.org/wiki/Telnet$ curl -v telnet://hogehoge.com:3306 * Rebuilt URL to: telnet://hogehoge.com:3306/ * Trying xx.xx.xx.xx... * TCP_NODELAY set * Connected to hogehoge.com (xx.xx.xx.xx) port 3306 (#0) Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file. * Failed writing body (0 != 29) * Closing connection 0上記出力はちょっとわかりづらいですが、接続自体は成功(Connected to hogehoge.comのところ)していて、出力を書き込むのに失敗しているような形。
ちょっと見ずらかったので使わなかったですが、出力の通りoutputオプションを使って--output /dev/null
など指定するのもいいかもしれません。
- 投稿日:2020-07-01T10:08:05+09:00
Linuxのカーネルパラメータについて
最近、カーネルパラメータを見直す機会があったのでメモしておきます。
カーネルパラメータを設定する目的
- サーバのパフォーマンスを最大限に引き出す
- セキュリティ強化
- TCP/IPなどプロトコルレベルでのチューニングによる効率化
注意事項
- カーネルパラメータはサーバの用途や環境によって最適な設定が変わるため、一部の設定値については言及しません
- 設定値列に
要検証
と記載します- カーネルパラメータを変更することによるリスクもあるため、充分検証して値を設定して下さい
カーネルパラメータ
ここ数年のチューニング情報を色々調べてみて、以下を設定すると良さそうでした。
パフォーマンス
パラメータ名 設定値 説明 fs.file-max 要検証 システム全体のファイルディスクリプタの上限 kernel.threads-max 要検証 システム全体のプロセス数の上限 net.core.netdev_max_backlog 要検証 カーネルがキューイング可能なパケットの最大個数 net.netfilter.nf_conntrack_max 要検証 netfilterでの最大同時コネクション数を調整する vm.swappiness 0 SWAPされやすさを設定する
※0でもSWAPされるときはSWAPするセキュリティ
パラメータ名 設定値 説明 kernel.sysrq 0 SysRq(システム要求)キーを無効にする net.ipv4.conf.all.accept_source_route 0 ソースルーティングを無効にする net.ipv4.conf.all.rp_filter 1 rp_filter(reverse path filter)を有効にする net.ipv4.conf.default.rp_filter 1 rp_filter(reverse path filter)を有効にする net.ipv4.ip_forward 0 IPの転送を無効にする net.ipv4.tcp_syncookies 1 tcp_syncookiesを有効にする ※SYN FLOOD対策 TCP/IPチューニング
パラメータ名 設定値 説明 net.core.rmem_max 要検証 TCPの受信バッファサイズの最大値を設定する net.core.somaxconn 要検証 TCPソケットが受け付けた接続要求を格納するキューの最大長 net.core.wmem_max 要検証 TCPの送信バッファサイズの最大値 net.ipv4.ip_local_port_range 要検証 TCP/IPの送信用ポート範囲の変更 net.ipv4.tcp_fin_timeout 5〜30 FINパケットのタイムアウト時間 net.ipv4.tcp_keepalive_intvl sec<75 TCP keepalive packetを送信する間隔(秒単位) net.ipv4.tcp_keepalive_time sec<7200 TCP keepalive packetを送信するまでの時間(秒単位) net.ipv4.tcp_keepalive_probes count<9 keepalive packetを送信する回数 net.ipv4.tcp_max_syn_backlog 要検証 ソケット当たりのSYNを受け付けてACKを受け取っていない状態のコネクションの保持可能数 net.ipv4.tcp_max_tw_buckets 要検証 システムが同時に保持するTIME_WAITソケットの最大数 net.ipv4.tcp_orphan_retries 要検証 こちらからクローズしたTCPコネクションを終了する前の再送回数 net.ipv4.tcp_rfc1337 1 RFC1337に準拠させる
※TIME_WAIT状態のときにRSTを受信した場合、TIME_WAIT期間の終了を待たずにそのソケットをクローズするnet.ipv4.tcp_slow_start_after_idle 0 通信がアイドル状態になった後のスロースタートを無効にする net.ipv4.tcp_syn_retries 3 tcpのSYNを送信するリトライ回数 net.ipv4.tcp_tw_reuse 1 TIME_WAIT状態のコネクションを再利用 tunedのプロファイルを参考にチューニングする項目を検討する
カーネルパラメータの設定項目はかなり数が多く、人間が管理しやすいようにするツールとしてtunedというものがあります。
tunedではサーバ種別に応じたプロファイルによってチューニングが行えるようになっており、それらの設定値を参考にチューニングする項目を検討してみました。
プロファイルについて
以下の通り、サーバ種別に応じたプロファイルが用意されています。
プロファイルにはチューニングにおける代表的なカーネルパラメータが記載されているので、こちらを参考にカーネルパラメータを検討してみます。
$ ls -l /usr/lib/tuned/ total 56 drwxr-xr-x. 2 root root 4096 Sep 9 2019 balanced drwxr-xr-x. 2 root root 4096 Sep 9 2019 desktop -rw-r--r-- 1 root root 14413 Mar 14 2019 functions drwxr-xr-x. 2 root root 4096 Sep 9 2019 latency-performance drwxr-xr-x. 2 root root 4096 Sep 9 2019 network-latency drwxr-xr-x. 2 root root 4096 Sep 9 2019 network-throughput drwxr-xr-x. 2 root root 4096 Sep 9 2019 powersave drwxr-xr-x. 2 root root 4096 Sep 9 2019 recommend.d drwxr-xr-x. 2 root root 4096 Sep 9 2019 throughput-performance drwxr-xr-x. 2 root root 4096 Sep 9 2019 virtual-guest drwxr-xr-x. 2 root root 4096 Sep 9 2019 virtual-host試しにvirtual-guestのテンプレートを見てみる
include=throughput-performance
という記載により、throughput-performance
のテンプレートをインクルードしていることが解ります。※設定値のみ表示するためコメント行は非表示にしています
/usr/lib/tuned/virtual-guest/tuned.conf[main] summary=Optimize for running inside a virtual guest include=throughput-performance [sysctl] vm.dirty_ratio = 30 vm.swappiness = 30インクルードしてる
throughput-performance
のテンプレートはこちらです。カーネルパラメータ以外にも、CPUやディスクの設定値が含まれていることが解ります。
/usr/lib/tuned/throughput-performance/tuned.conf[main] summary=Broadly applicable tuning that provides excellent performance across a variety of common server workloads [cpu] governor=performance energy_perf_bias=performance min_perf_pct=100 [disk] readahead=>4096 [sysctl] kernel.sched_min_granularity_ns = 10000000 kernel.sched_wakeup_granularity_ns = 15000000 vm.dirty_ratio = 40 vm.dirty_background_ratio = 10 vm.swappiness=10virtual-guestの場合のカーネルパラメータ設定
tunedで設定されているカーネルパラメータを試しに設定し、実際に設定された値を以下の通り一覧にしてみました。
Includeしているテンプレートと同じ設定値があった場合はマージしてくれるようなのですが、
vm.swappiness=30
になっていることから必ずしもInclude後に上書きするわけでは無いようです。
パラメータ名 設定値 説明 vm.dirty_ratio 40 ディスクにコミットされる前にダーティページで満たすことができるシステムメモリの絶対最大量 vm.swappiness 30 SWAPされやすさを設定する kernel.sched_min_granularity_ns 10000000 単一のタスクが実行されるターゲットの最小スケジューラ期間 kernel.sched_wakeup_granularity_ns 15000000 タスクが起動したときのプリエンプションの粒度 vm.dirty_background_ratio 10 ダーティーページの割合がこの値に達すると優先度の低いバックグラウンドでpdflushが書き出し動作する 試しにnetwork-throughputのテンプレートを見てみる
include=throughput-performance
という記載により、throughput-performance
のテンプレートをインクルードしていることが解ります。※設定値のみ表示するためコメント行は非表示にしています
/usr/lib/tuned/network-throughput/tuned.conf[main] summary=Optimize for streaming network throughput, generally only necessary on older CPUs or 40G+ networks include=throughput-performance [sysctl] net.ipv4.tcp_rmem="4096 87380 16777216" net.ipv4.tcp_wmem="4096 16384 16777216" net.ipv4.udp_mem="3145728 4194304 16777216"インクルードしている
throughput-performance
のテンプレートは前項にて記載済みのため割愛します。network-throughputの場合のカーネルパラメータ設定
tunedで設定されているカーネルパラメータを試しに設定し、実際に設定された値を以下の通り一覧にしてみました。
Includeしているテンプレートと同じ設定値があった場合はマージしてくれるようなのですが、
vm.swappiness=30
になっていることから必ずしもInclude後に上書きするわけでは無いようです。
パラメータ名 設定値 説明 vm.dirty_ratio 40 ディスクにコミットされる前にダーティページで満たすことができるシステムメモリの絶対最大量 vm.swappiness 30 SWAPされやすさを設定する kernel.sched_min_granularity_ns 10000000 単一のタスクが実行されるターゲットの最小スケジューラ期間 kernel.sched_wakeup_granularity_ns 15000000 タスクが起動したときのプリエンプションの粒度 vm.dirty_background_ratio 10 ダーティーページの割合がこの値に達すると優先度の低いバックグラウンドでpdflushが書き出し動作する net.ipv4.tcp_rmem 4096 87380 16777216 TCPソケットの受信バッファサイズ(min, default, max) net.ipv4.tcp_wmem 4096 16384 16777216 TCPソケットの送信バッファサイズ(min, default, max) net.ipv4.udp_mem 3145728 4194304 16777216 UDPソケットのバッファサイズ(min, default, max) tunedのプロファイルを参考にカーネルパラメータを設定するか否か
- 結論
- プロファイルとサーバ用途によって参考にするものを選択する
- 理由
virtual-guest
プロファイルの場合は基本的にサーバ構築時のデフォルト(サーバごとに変わる)と同じものが設定されているnetwork-throughput
プロファイルの場合はバッファサイズがデフォルトから引き上げられている
- スループットが求められるサーバに設定する時の参考にする
vm.swappiness
やvm.dirty_ratio
については利用する環境に応じて適宜変える方針が良さそう- CPUやディスクの項目については別途検討の余地あり
おわりに
サーバごとにカーネルパラメータを適正に設定することは、セキュリティ・パフォーマンスの観点で意味のあることだと思います。
昨今、k8sなどコンテナ技術の人気が上昇していますが、そうは言ってもオンプレ・クラウドに限らずサーバを運用する機会はまだまだあると思われるので、適切に設定していきたいですね。
参考リンク
- CentOS7 カーネルパラメータ チューニング
- webのためのカーネルパラメータ
- 投稿日:2020-07-01T09:45:17+09:00
【初心者向け】cronを利用したプロセス監視
はじめに
今回のこの記事を書こうと思ったのは、前回のcronについてのまとめとよくあるエラーでcronについてのまとめを書いたので、前回に続いてcronを利用したプロセス監視について書こうと思います。
前回と同じく初心者向けの記事になります。
cronについては細かく書かないので、cronについてあまり知らない方は前回の記事を閲覧するか、調べて頂いてから見ると分かりやすいかと思います。
スクリプト概要
プロセス監視
- pgrepで対象のプロセス一覧を表示し、その一覧から監視しているスクリプトが何個起動しているか確認する。
- その結果をif文で分岐して、分岐内の必要な処理をする。
コード
vicrontab -e */5 * * * * /bin/sh shell.shShellScript#! /bin/bash PROCESS_NAME=nginx count=`pgrep $PROCESS_NAME | wc -l` if [ $count = 0 ]; then echo "$PROCESS_NAME is stop" systemctl start nginx echo "$PROCESS_NAME is Start" else echo "$PROCESS_NAME is running" fi解説
vicrontab -e */5 * * * * /bin/sh shell.sh //crontabの中に上記のように記述すると5分毎に設定したシェルを実行するようになります。 */5 * * * * /bin/sh shell.sh >> /任意の場所/log.txt 2>&1 //もしファイルとして実行した内容を残したければこのように記述することもできます。 //2>&1で標準出力とエラーを混ぜて出力されます。ShellScript#! /bin/bash //これはシェルを書く上での決まり文句みたいなものですね。 PROCESS_NAME=nginx //ここで監視したいプロセスを定義します。今回だとnginxですね。 count=`pgrep $PROCESS_NAME | wc -l` //動作しているプロセスをカウントしたいのでプロセスの数を数えて変数に代入します。 //pgrepでパターンにマッチしたプロセスIDの一覧を取ってくる。 // |(パイプライン)でwc -lを繋いでプロセスの行数を取ってくる。 ※余談ですが、wcはword countが名前の由来で行数以外にも単語・バイト数なども表示できます。 if [ $count = 0 ]; then echo "$PROCESS_NAME is stop" systemctl start nginx echo "$PROCESS_NAME is Start" else echo "$PROCESS_NAME is running" fi //このif文で先程定義したプロセスの数が0の場合はnginxが停止していることが分かるので上記のような起動するシェルを書きます。 //そうでない場合は、nginxのプロセスが正常に起動しているので、それに対してecho "$PROCESS_NAME is running"と返します。
- このcronの設定と解説したシェルスクリプトを組み合わせると簡単ですが、5分毎にシェルを実行してプロセスの確認を行い、もしプロセスが停止していた場合は自動で起動するようにできます。
参考サイト
- 下記の記事などを閲覧するとシェルスクリプトについて理解が深まると思います。
初心者向けシェルスクリプトの基本コマンドの紹介
UNIX&Linuxコマンド・シェルスクリプトリファレンス最後に
今回は前回書いた記事の続きでcronを利用したプロセス監視についての記事を書きました。
間違いなどありましたらコメント等で教えて頂けると私の勉強にもなるので是非お願いします。
次回はVagrantやミドルウェアの設定などについての記事が書けたら良いなと思っています。
- 投稿日:2020-07-01T01:53:52+09:00
Perlを1行でセグフォらせる
はじめに
なんか最近の流行りっぽいので。
- pythonを三行でセグフォらせる
- pythonを2行でセグフォらせる
- pythonを1行でセグフォらせる
- Pythonを33文字でセグフォらせる
- Pythonをctypesを使わずに1行でセグフォらせる
- Rustを5行でセグフォらせる
- C言語で16文字でセグフォらせる
ということで、Perlでやってみました。環境は適当な x86_64 の Linux です。
どうやるの?
ほらこんなに簡単!
いやそういうことじゃなくて
気を取り直して。
WSL/Ubuntu18/Perl5.26.1で実行$ perl -e 'syscall 10,$m-=4096,4096,0 while$m||=1<<47' Segmentation fault (core dumped)シェル芸botで試すとこんな感じ。こっちでもめでたくセグフォになりました。
なにやってるの?
これをもうちょっと見やすくするとこんな感じです。
元ネタrequire 'syscall.ph'; $m=0x800000000000; while ( 1 ) { $m-=0x1000; syscall &SYS_mprotect,$m,0x1000,0; }つまり、さっきのワンライナーは、あるアドレス値を起点として、延々と mprotect システムコールを発行するものだったということです。
※syscallがシステムコールを呼び出す関数で、10 というのが mprotect に相当する番号。これでどんな効果があるかというと、指定したメモリ領域の保護属性の変更です。
第3引数の 0 は、PROT_NONE
相当なので、そのメモリ領域に対する、読み書き・プログラム実行全ての許可が失われます。なので、メモリアクセスした瞬間にSEGVが飛んでくるようになるわけです。なお、開始アドレスとしている 0x800000000000 は、64bitプロセスのメモリの末尾 ( heap,stack,vdso ) が大体ここの直前に配置されることから決めてます。
メモリマップの確認$ perl -e 'system "cat","/proc/$$/maps"' 7f11879f0000-7f11879f9000 r-xp 00000000 00:00 121160 /lib/x86_64-linux-gnu/libcrypt-2.27.so 7f11879f9000-7f11879fa000 ---p 00009000 00:00 121160 /lib/x86_64-linux-gnu/libcrypt-2.27.so 7f11879fa000-7f1187bf8000 ---p 0000000a 00:00 121160 /lib/x86_64-linux-gnu/libcrypt-2.27.so (略) 7f1188c00000-7f1188df7000 r-xp 00000000 00:00 135847 /usr/bin/perl 7f1188df7000-7f1188df8000 r-xp 001f7000 00:00 135847 /usr/bin/perl 7f1188ff8000-7f1188ffe000 r--p 001f8000 00:00 135847 /usr/bin/perl 7f1188ffe000-7f1189000000 rw-p 001fe000 00:00 135847 /usr/bin/perl 7fffbe41b000-7fffbe45d000 rw-p 00000000 00:00 0 [heap] 7fffc523e000-7fffc5a3e000 rw-p 00000000 00:00 0 [stack] 7fffc6124000-7fffc6125000 r-xp 00000000 00:00 0 [vdso]もっとやばいの
※7/2追加
もっと面白かったり短かったりする方法はないのかな、と探していてやばいのを見つけてしまいました。
$ perl -e 'unpack p,1x8' Segmentation fault (core dumped)…なんじゃこりゃ?? と思い、調べてみました。
まず、
unpack
というのはpack
と対になる組み込み関数であり、端的に言うとデータのシリアライズ (pack
) と、デシリアライズ (unpack
) を担当するものです。
これは、単数~複数のデータをまとめて文字列化し持ち運べるようにしたり、また逆に文字列からデータを取り出すために使います。ここで
p
は文字列'p'
を裸で指定したものです。これはまとめる/まとめたデータの種類を表すものですが、マニュアルによるとこうあります。packのマニュアルより:
p ヌル文字で終端する文字列へのポインタ。
…ポインタ?? あなた「ポインタ」言いましたか!?
なんと、こんなところで裸のポインタを使うための機能が隠れているとは。流石Perl。どこで使うんだコレ。
気を取り直して。
pack
で使った場合、どうやら文字列データを保持している内部的なアドレス値をシリアライズして文字列化するようです。次のようにデバッガで見てみると、見事に一致します。gdbでメモリを覗く$ perl -e '$x="angel_p_57";print pack "p",$x;close STDOUT;sleep 1200'|od -tx8 & sleep 1 [2] 1067 0000000 00007fffbc94a320 0000010 $ ps -fC perl UID PID PPID C STIME TTY TIME CMD angel 1066 12 0 23:53 pts/0 00:00:00 perl -e $x="angel_p_57";print pack "p",$x;close STDOUT; $ sudo gdb perl …(略)… (gdb) attach 1066 …(略)… (gdb) x/s 0x00007fffbc94a320 0x7fffbc94a320: "angel_p_57"※
x/s
コマンドで指定している 0x00007fffbc94a320 というのが、pack
で生成された文字列の元になったアドレスで、出力させたものをod -tx8
によって16進で見ているわけです。ということは逆に
unpack
で使うと、文字列をデシリアライズしてアドレス値として解釈しそこにある文字列の複製を生成する、ということになります。なので、デタラメな文字列を指定すると、即不正メモリアクセスというわけです。
ただ、おそらく x86_64-Linux な Perl だと、アドレス値のデシリアライズには8文字を要するようで、なので1x8
で11111111
という文字列を使っています。(x
は文字列繰り返しの演算子 )いや、
pack
にそんな機能があるなんて知らなかったよまだまだPerlも奥が深いな、と思うことしきりでした。おわりに
意外と不正メモリアクセスを作るのに苦戦し、思いついた手法がコレでした。
メモリ領域自体を不正扱いにしちゃえばいいじゃんと。
何か他にも面白い方法があればぜひ。
- 投稿日:2020-07-01T00:12:47+09:00
Progateで出てきたLinux(UNIX)コマンドまとめ
記事を書くきっかけ
現在ProgateでCommandLineの勉強をしているのですが、
まとめるのが下手なのと、自分のメモを見返した時にわかりやすくするために、Progate内で出てきたLinuxコマンドについてまとめようと思い、今回記事を書くことにしました。
CommandLineとは?
簡潔にいうと、「Linux/UNIXコマンドのこと」なのですが、
ちゃんと説明すると、Windowsのコマンドプロンプトや、Macのターミナルを文字だけで操作する時に使用します。
教材で出てきたコマンド一覧
コマンド一覧 意味 touch ファイルを作成する cat ファイルの中身を表示 mkdir ディレクトリ作成 cd ディレクトリを移動 ls ディレクトリの中身を確認 mv ファイル/ディレクトリの移動&名前の変更 cp ファイルのコピー rm ファイルの削除 rm -r ディレクトリの削除 まとめ
現在は、Progateのみで勉強していますが、7/2に、新しいLinuxの教科書が届くので、そちらを使って再度、勉強を続け、理解した内容については、本の丸写しにならないように、自分の見解も兼ねて、書きたいと思います。
以上です。
参照ページ