コマンド file
file コマンドは、ファイルの先頭部分を解析して、そのファイルが何なのか教えてくれる。
$ file /bin/ls /etc/hosts /usr/bin/yum /bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=c8ada1f7095f6b2bb7ddc848e088c2d615c3743e, stripped /etc/hosts: ASCII text /usr/bin/yum: Python script, ASCII text executable
バイナリファイルの場合が特に詳しい表示になる。で、ちょっと詳しくみてみる。
ELF - Executable and Linkable Format はバイナリ形式の規格。昔は COFF(Common Object File Format)なんてのもあった。
LSB - least significant bit は本来、2進数の最下位ビットなんだけど、この場合は Little Endian の意味合いが強い。今のように Intel / AMD 系のCPUが独占する前は、結構CPUも多様で MIPS の設計では同じモデルでも、LSB, MSB オプションがあったりした。
SYSV - AT&T 直径の System V の略だね。
BuildID - RHEL 6 以降で採用されているチェックサムで、セキュリティ向上な感じか?
stripped - 実行に必要ないバイナリデータ(もっぱらデバッグ用のシンボル類)を削除済み。
で、MacOSもUNIXの仲間(Mach)だから、file コマンドを試してみる。
$ file /bin/ls /bin/ls: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e] /bin/ls (for architecture x86_64): Mach-O 64-bit executable x86_64 /bin/ls (for architecture arm64e): Mach-O 64-bit executable arm64e
おお、複数アーキテクチャに対応してる。面白い。
シェルスクリプト #!
シェルスクリプトは先頭の1行にどんなシェルプログラムを利用するかを指定する事になっている。→シェバン(shebang)
#! /bin/bash
てな具合。昔はシェルといえば sh (Bourne)しかなかったから気にならなかったけれど、BSDに csh が搭載されるようになると B か C 迷うので対策が考えられた。sh には何もしない(NOP: No operation) コマンドというのがあって、それが先頭にあるとB、コメント # なら C というやつ。
: ホゲホゲ ⇦ Bsh # シカジカ ⇦ Csh
古いUNIXの書物(McGraw-Hill の Unix Worldとか、1990年初頭にちょくちょく投稿していた)だと、これが常識。1行目をみて「あ、これはCshなのね」という感じ。
この小ネタとしては、# は Bsh, Csh ともにコメントで : は Bsh では NOP という事。具体的には # は両シェルとも読み飛ばす(無視)するけど、: はイチよ〜 Bsh は解析するので多少処理時間がかかる。
CentOS 7 の sh はもやは bash だけど(/bin/sh が /usr/bin/bash へのリンク) 1万行の : と # のファイルを実行してみた。すると
$ time bash colon real 0m0.028s user 0m0.025s sys 0m0.003s< $ time bash hash real 0m0.015s user 0m0.010s sys 0m0.005s
今でも : の方が処理時間がかかる。くどいけど csh (これまた tcshだけど)でもやってみた。
$ time csh colon real 0m0.179s user 0m0.116s sys 0m0.063s $ time csh hash real 0m0.051s user 0m0.036s sys 0m0.015s
同様に : の方が時間がかかる。というか csh 重いなぁと今更ながら思うのであった。