こりゃ知らんかったシェルのコマンドなど

最近改めてコンパイラなどの勉強をしており、その過程で知った「こりゃ知らんかったわ～」というシェルのコマンドや特殊変数、オプションなどを書き留めておきます。
中には恥ずかしながら「それ知らんかったんかい！」というのも含まれていますが、備忘録として残しておきます。
※Amazon Linux上のbashで確認

# 特殊変数 $?
直前のコマンドの終了ステータスを保持する変数。

```bash:
$ echo 'Hello'; echo $?
Hello
0
$ cat nofile.txt; echo $?
cat: nofile.txt: そのようなファイルやディレクトリはありません
1
```

# true, falseコマンド
`true`コマンドは必ず終了ステータス0（成功）を返すコマンド、`false`コマンドは必ず1（エラー）を返すコマンド。

```bash:
$ true; echo $?
0
$ false; echo $?
1
```

あまり使いどころがないように思えますが、手元のMacで`cat /etc/passwd`をすると、

```bash:
sshd:*:75:75:sshd Privilege separation:/var/empty:/usr/bin/false
```

のようにログインシェルに`false`コマンドが指定されており、
これは`sshd`ユーザでログインしようとすると`false`コマンドが実行されて結果ログインできない、というような使われ方をしています。

# fileコマンド
ファイルの中身を良しなに解釈してくれて、情報を表示してくれるコマンド（説明が雑）。

```bash:
$ file /bin/bash
/bin/bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.35, BuildID[sha1]=6d4bc8a9x214f83cdea6a8xfe639d4d560984cad, stripped
$ file hoge.txt
hoge.txt: UTF-8 Unicode text, with very long lines
```

# unameコマンド
システムの情報を表示するコマンド。
オプションなしだとOSの名前だけ表示、`-a`を指定すると全情報表示となります。

```bash:
$ uname
Linux
$ uname -a
Linux ip-10-0-1-159 4.1.7-15.23.amzn1.x86_64 #1 SMP Mon Sep 14 23:20:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
```

# hexdumpコマンド
ファイルの中身を16進数や8進数などの形式で表示してくれます。デフォルトは2バイト刻みの16進数4桁で表示されます。これでバイナリファイルも怖くない（？）

```bash:
$ hexdump /bin/cat
0000000 457f 464c 0102 0001 0000 0000 0000 0000
...
000bb70 0001 0000 0000 0000 0000 0000 0000 0000
000bb80
```
# objdumpコマンド
オブジェクトファイルを逆アセンブルしてくれるコマンド。

```bash:
$ objdump -d /bin/cat
/bin/cat:     ファイル形式 elf64-x86-64


セクション .init の逆アセンブル:

0000000000401540 <.init>:
  401540:       48 83 ec 08             sub    $0x8,%rsp
  401544:       48 8b 05 9d 9a 20 00    mov    0x209a9d(%rip),%rax        # 60afe8 <__sprintf_chk@plt+0x209618>
  40154b:       48 85 c0                test   %rax,%rax
  40154e:       74 05                   je     401555 <__uflow@plt-0x1b>
  401550:       e8 9b 02 00 00          callq  4017f0 <__gmon_start__@plt>
  401555:       48 83 c4 08             add    $0x8,%rsp
  401559:       c3                      retq

セクション .plt の逆アセンブル:
...
```
# readelfコマンド
ELFファイルの情報を表示してくれるコマンド。
wikipediaによるとELFとは

> コンパイラが生成するオブジェクト、および、ライブラリとリンクされた実行ファイルのファイルフォーマット

とのことです。
オブジェクトファイルのシンボル一覧を表示するのに使う模様。

```bash:
$ readelf -h /bin/cat
ELF ヘッダ:
  マジック:  7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  クラス:                            ELF64
  データ:                            2 の補数、リトルエンディアン
  バージョン:                        1 (current)
  OS/ABI:                            UNIX - System V
  ABI バージョン:                    0
  型:                                EXEC (実行可能ファイル)
  マシン:                            Advanced Micro Devices X86-64
  バージョン:                        0x1
  エントリポイントアドレス:          0x4025f4
  プログラムの開始ヘッダ:            64 (バイト)
  セクションヘッダ始点:              46144 (バイト)
  フラグ:                            0x0
  このヘッダのサイズ:                64 (バイト)
  プログラムヘッダサイズ:            56 (バイト)
  プログラムヘッダ数:                8
  セクションヘッダ:                  64 (バイト)
  セクションヘッダサイズ:            29
  セクションヘッダ文字列表索引:      28
```
# サブシェル
`()`でコマンドを囲うと、呼び出し元のシェルに影響を与えずに環境変数などの変更ができます。

```bash:
$ HOGE=hoge
$ echo $HOGE
hoge
$ (HOGE=fuga; echo $HOGE); echo $HOGE
fuga # サブシェル内のHOGE
hoge # 親シェルのHOGE
```

# おわりに
GNU開発ツールは偉大。