20200701のLinuxに関する記事は11件です。

「UNIXという考え方―その設計思想と哲学」を読んだ

0. はじめに

こんにちは。都内でエンジニアをしている、@gkzvoiceです。
先日、Twitterのタイムラインに@nukumaro22さんからこんな投稿が流れてきました。

というわけで、早速、Amazonでポチり、読んでみました。

UNIXという考え方―その設計思想と哲学

本書を読んで、覚え書きをしていたので、インターネットに放流したいと思います。
書評っぽい内容ですが、タイトルに書評と付け忘れました。。

1. 本書の目次

  • 第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を拝見して腑に落ちた

  • 自分の言葉で説明すると、こんな具合
    • 複雑性は増すけどよりよい設計と、それらは劣るけど単純な設計のうち、後者を選択すると、コントリビュートの敷居を下げ、長い目で見ると前者より優れたものとなる。

3-3.Worse is betterの先にあるもの

  • 本書では、Worse is betterについて、このように続けている。

「良くなる」ためには、単純さを犠牲にして完全性を追求しなければならない。そうなるとUNIXはもはやUNIXではなくなる。

3-4.本書の話題から外れるけどLinuxカーネルのメンテナーの仕事内容

  • @komi_edtr_1230さんの投稿を拝見してLinuxカーネルのメンテナーの仕事の内容が気になった
  • これは宿題

P.S. Twitterもやってるのでフォローしていただけると泣いて喜びます:)

@gkzvoice

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 right
180度回転
xinput set-prop 13 'Coordinate Transformation Matrix' -1 0 0 0 -1 0 0 0 1
xrandr -o inverted 
0度に戻す
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に書き換える

関連する数学

アファイン変換(affine transformation)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

macOSでクリップボードにある文章の文字数を数える

背景

  • 文字数をカウントしてくれるwebサービスを使うことがあった.
  • でもいちいちブラウザに切り替えてコピペして文字数みてまた書き直して…という作業がめんどくさい.
  • MS Word とかいう邪悪なソフト使いたくない.
  • 文章の一部をいちいち別のファイルにコピペして wc コマンド叩くのもめんどくさい.
  • Neovim で文章を書くことが多いからターミナルだけで作業を完結させたい.
    • 具体的にはこれと同じ機能をターミナルだけでやりたい

方法

pbpaste | wc -m

解説

  • pbpaste: クリップボードのデータを標準出力する.テキストならテキストが出力される. Finder でファイルをコピーしたならファイル名が出力される.
  • wc -m: 文字数を数えてくれる. -m オプションでマルチバイト文字にも対応してくれる.
  • パイプを使って pbpaste の出力を wc -m の入力として受け取り,最終的に wc -m の結果を出力する.

応用例

行数も含めた文字数を数えたい

-l オプションを追加します.

pbpaste | wc -ml

2個の数値が出力されるようになり,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 -m

Shift_JIS

pbpaste | nkf -s | wc -m

EUC-JP

pbpaste | nkf -e | wc -m

UTF-16

pbpaste | nkf -w16 | wc -m

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WSL 上で同一ディストリビューションの環境を複数インストール・管理する

Microsoft Storeから WSL 環境をインストールすると、1種類のディストリビューションは1個の環境としてしかインストールできない(と思う)。
image.png
だが同一ディストロの環境を気軽に複数作ったり壊したり消したり、使い捨てで使いたいこともあるだろう。ターミナルから簡単に環境を複製できるのでやり方を書いておく。

手順

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 のタイトルバーの ボタンから表示できる環境リストから選んで起動するなりすればよい。
image.png

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$\ 下にマウントされているのでそちらからエクスプローラーでブラウジングすることができる。
image.png
いらなくなった環境を削除したいときは、wsl --unregister (登録名) で削除できる。

わりと簡単に環境を複製・破壊・廃棄できるので、気兼ねなく遊んでみよう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

故障対応の原因切り分けで知っておきたいコマンド集(サーバ編)

システム系コマンド

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.00

2~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 st

4~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 Mem

CPU、メモリ、ディスク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  0

CPU、ディスク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/fstab

Linuxカーネルが出力したメッセージを確認(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.8

TCPソケットの接続状況を確認(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 -nr

ARPキャッシュテーブルを確認

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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

IT技術界のレジェンドを知りたい

皆さんが知っているIT技術界の「スゴイ人」を教えて頂けないでしょうか!!!orz

はじめに

本記事に技術情報は一切ありませんし、誰か教えて!っていう大変他人任せで低レベルな記事です。タイトルからわかるかと思いますが、適当にタグをつけております。すみませんがご了承ください。
不快な方はスルー推奨です。

また後日、教えてもらった技術者を調べてみて、特に気になった方2,3人を再度記事にしてみたいなと思っております。(私なんかの文章読みたい人なんていないと思いますが、教えて頂いた方への感謝・尊敬の念を込めて。)

レジェンド(憧れの存在)がもたらす効果

どんな業界でもレジェンドの存在は憧れ、希望を生み、業界全体のレベルアップに繋がると思います。

私が好きなバスケ界では、マイケルジョーダン、マジックジョンソン、ラリーバードなどなど多くのレジェンドたちの存在がありました。
私の学生時代はアイバーソン、コービー、ナッシュ、シャックなどなどのスーパースターがNBAを引っ張っていました。ジェイソンウィリアムズの肘パスは誰もが一度練習したでしょう。(笑)
そうです。普段のモチベーションに「憧れ」は必要だと思うんです!!!

white.jpg

私は知らない!(ドン!!!)

私は大卒後、社会人からエンジニアになり今年で5年目になります。(早いなー)
学生時代は全くITに興味がありませんでした。そのためスゴイ技術者・経営者を全く知りません。orz
Appleのスティーブジョブズ&ウォズニアックコンビ、Microsoftのビル・ゲイツ、facebookのザッカーバーグ、Googleのラリー・ペイジ、Amazonのジェフ・ベゾス、Oracleのラリーエリソンくらいなら(名前だけ)もちろん知っています。

↓ウォズ
wozu .jpeg

そしてそして、日本人技術者の名前を本当に知りません!!
これは実際悲しいことですが、若手技術者の多くはそんなもんじゃないでしょうか。
私が知っているのは堀江貴文さん、西村ひろゆきさん、つくばの落合さん等メディアに出ている人たちくらいです。(本当はもう少し知っています。)

おすすめのレジェンド教えてください

私はIT業界は少数の天才たちによって支えられているんじゃないかと思っています。知らんけど。

そこで!日本のIT系技術者・経営者で(もちろん外国の方でも嬉しいです。)おススメのレジェンドの方を教えて頂けないでしょうか。またはこんなすごいことが現在進行形で行われている。などなど
(インフラ技術開発者・ソフトウェア開発者・OSS開発者・言語開発者・伝説的な経営者)

この人はこんな方だ!というコメントもあればぜひ調べ、書籍もあったら読んでみます。
私のこれからのエンジニア人生のため、皆さんのモチベーションを高めるために!orz
※ある程度調べれば出てくる人でないと情報ゲットできないので調べれば出てくる方でお願い致します。
好奇心を満たしたいだけなので何卒お気軽に。。

「IT業界」と、本当にざっくりしていて恐縮ですが よろしくお願い致します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 GMT

DBやキャッシュへの接続確認

とあるサーバ(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 など指定するのもいいかもしれません。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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=10

virtual-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.swappinessvm.dirty_ratioについては利用する環境に応じて適宜変える方針が良さそう
    • CPUやディスクの項目については別途検討の余地あり

おわりに

サーバごとにカーネルパラメータを適正に設定することは、セキュリティ・パフォーマンスの観点で意味のあることだと思います。

昨今、k8sなどコンテナ技術の人気が上昇していますが、そうは言ってもオンプレ・クラウドに限らずサーバを運用する機会はまだまだあると思われるので、適切に設定していきたいですね。

参考リンク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者向け】cronを利用したプロセス監視

はじめに

  • 今回のこの記事を書こうと思ったのは、前回のcronについてのまとめとよくあるエラーでcronについてのまとめを書いたので、前回に続いてcronを利用したプロセス監視について書こうと思います。

  • 前回と同じく初心者向けの記事になります。

  • cronについては細かく書かないので、cronについてあまり知らない方は前回の記事を閲覧するか、調べて頂いてから見ると分かりやすいかと思います。

スクリプト概要

  • プロセス監視

    • pgrepで対象のプロセス一覧を表示し、その一覧から監視しているスクリプトが何個起動しているか確認する。
    • その結果をif文で分岐して、分岐内の必要な処理をする。

コード

vi
crontab -e 

*/5 * * * * /bin/sh shell.sh


ShellScript
#! /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

解説

vi
crontab -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やミドルウェアの設定などについての記事が書けたら良いなと思っています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Perlを1行でセグフォらせる

はじめに

なんか最近の流行りっぽいので。

ということで、Perlでやってみました。環境は適当な x86_64 の Linux です。

どうやるの?

ほらこんなに簡単!

image.png

いやそういうことじゃなくて

気を取り直して。

WSL/Ubuntu18/Perl5.26.1で実行
$ perl -e 'syscall 10,$m-=4096,4096,0 while$m||=1<<47'
Segmentation fault (core dumped)

シェル芸botで試すとこんな感じ。こっちでもめでたくセグフォになりました。

image.png

なにやってるの?

これをもうちょっと見やすくするとこんな感じです。

元ネタ
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文字を要するようで、なので 1x811111111 という文字列を使っています。( xは文字列繰り返しの演算子 )

いや、packにそんな機能があるなんて知らなかったよまだまだPerlも奥が深いな、と思うことしきりでした。

おわりに

意外と不正メモリアクセスを作るのに苦戦し、思いついた手法がコレでした。
メモリ領域自体を不正扱いにしちゃえばいいじゃんと。
何か他にも面白い方法があればぜひ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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の教科書が届くので、そちらを使って再度、勉強を続け、理解した内容については、本の丸写しにならないように、自分の見解も兼ねて、書きたいと思います。

以上です。

参照ページ

Progate(CommandLine)

「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む