はじめに
POSIX のコマンド一覧を見てやけに少ないなと思ったことはないでしょうか?例えば useradd
がないのでユーザーが作れませんしcrontab
はあるのに cron
がないと中途半端です。重要なものがいくつも欠けおり、あれだけのコマンドでは到底 Unix を使うことができません。実は「Unix に実装すべき最低限の仕様」を定義した標準規格は他にありました。それが UNIX をこの世に生み出した AT&T 自身による標準規格 System V Interface Definition (SVID) です。この記事は POSIX に敗れて消えてしまったもう一つの UNIX 標準規格 SVID ・・・のコマンドの話です。(私の知識不足により C 言語インターフェースの話は含まれません。)
SVID と POSIX の歴史
SVID は POSIX よりも早く標準規格を発表しています。ただし SVID1 登場の一年前に /usr/group によって /usr/groupd Standard という標準規格が発表されています。/usr/groupd Standard には IEEE や ISO も貢献しており、これが POSIX の基礎となっているようです。
- 1981: /usr/group 標準化委員会で標準化作業が始まる(のちに POSIX の基礎となる)
- 1984: /usr/group Standard 完成(System III ベース + BSD)
- 1985: SVID1 (System V Release 2 対応)
- 1986: SVID2 (System V Release 3 対応)
- 1988: POSIX.1 (IEEE Std 1003.1-1988)
- 1989: SVID3 (System V Release 4.0 対応)
- 1992: POSIX.2 (IEEE Std 1003.2-1992)
- 1995: SVID4: XPG4 と POSIX 1003.1-1990 に準拠するように更新
- 2001: POSIX.1-2001 (IEEE Std 1003.1-2001)
- POSIX.2 が統合。その他の標準仕様が同期され現在の形となる
- 2008: POSIX.1-2008 (IEEE Std 1003.1-2008)
- 最新の POSIX は POSIX.1-2008 2017 edition (バグ修正版)
- 202x: POSIX.1-202x (2022 年後期予定)
もう少し詳細な歴史や各仕様へのリンク先は「POSIXとUnix関連の標準規格と歴史年表 (IEEE, SVID, XPG, SUS)」を参照してください。
UNIX と POSIX の方向性の違い
SVID1 が登場した頃、すでに Unix は System V 系と BSD 系に分かれていました。4BSD がリリースされた頃です(ちなみに Linux は誕生しておらず GNU プロジェクトは開始したばかりです)。System V Interface Definition はその名の通り、System V という OS を定義するものであり BSD の事情は(基本的に?)考慮されていません。一方 POSIX は Portable Operating System Interface (移植可能な OS のインターフェース)の略からも分かるように System V と BSD など複数の OS でソフトウェアが移植可能になるように考慮されています。その方針の違いが標準仕様の内容にも現れています。
SVID は Unix (System V)として必要だと考えたものをすべて定義しました。一方 POSIX は複数の Unix (System V と BSD) で共通で動く最低限のものだけを抜き出して定義しました。AT&T が考えた System V のコマンドは、System V と BSD の両方で動くコマンドよりも多いです。つまり POSIX は Unix 系 OS が持っていなければならないとするすべてのコマンドを定義しているわけではないということです。(C 言語用インターフェースも同じだと思いますが調べていません)。
- SVID ・・・ Unix (System V) が持つべき最低限の仕様
- POSIX ・・・ Unix (System V、BSD 等) で共通して使える最低限の仕様
似たような文章ですが、この 2 つは POSIX の方が仕様が少ないと言うだけではなく異なる結果をもたらします。SVID の場合は必要があると思ったら新しい仕様を追加することが比較的簡単に行うことができます。時代に合わせて新しい機能コマンドを追加していくことができますし、正確で漏れがない仕様にすることで System V を実装する環境の間で高い移植性を実現することができたでしょう。しかし POSIX の場合はそうはいきません。各環境でバラバラに実装されているものの中から共通で使えるものだけを仕様にするという方針なので標準化される内容は少なく、基本的に仕様が作られるよりも実装の開発が先行します。(POSIX 準拠の新しい実装を開発するプロジェクトは別です。そのようなプロジェクトとして toybox があります。)
POSIX は実際の実装の中から共通分母を取り出して作られたものなので、POSIX が作られた時点では、各 OS ベンダーが POSIX に準拠するのは簡単だったでしょう(互換性がない部分はそもそも仕様に含まないので当然ですね)。それが当時 POSIX が支持された理由の一つだと思います。また POSIX は厳格なものでも絶対的なものでもなく、POSIX の定めた仕様に従うような強制はしませんでした。POSIX は未定義の部分が多く完全なものにはなっていませんが、それは将来への拡張が行えるようにするための意図的なものです。実装は POSIX に準拠しつつも自由に拡張を行うことができます。OS ベンダーに自由に拡張する余地(それはロックインに利用可能です)が与えられたことも POSIX が支持された理由の一つでしょう。
しかしこの方針は POSIX 主導で仕様が作られることはないということを意味します(その例外として POSIX 主導で仕様が作られた pax コマンドがありますが現状を見れば分かる通り tar
コマンドを置き換えることはできませんでした)。そのため POSIX 標準化時点ですでに互換性がないものや新しく登場するコマンドやオプション(例 route
コマンドや date
コマンドのオプション)は実装者のさじ加減で決まるため互換性が低くなってしていまいました。すべての実装で同じように実装されなければ POSIX の仕様に取り入れられることはありませんし、古いナンセンスな仕様も残り続けます。そして POSIX は 30 年の間、ほとんど仕様が改定されず、新たな互換性の問題が発生するという残念な結果になっています。(とは言えオープンソース文化が発達したおかげで被害は最小限で済んでいます。今はそれぞれのベンダーが新しいコマンドを作る必要はなくに単に移植するだけです。)
少し話がそれましたが、SVID は Unix 戦争に負けはしましたが、Unix を誕生させたのは AT&T です。Unix というものを一番正しく理解していたのは AT&T と考えても間違いないでしょう。また BSD との移植性を考えることなく、Unix の正統系列である System V に必要なコマンドを定義しました。つまり SVID こそが真の Unix の標準規格であると考えても過言ではないと思います。(異論あり。コメント参照)
ということで、本来 Unix という OS が持っていなければならなかったコマンドとはなにか?というのを過去の SVID 標準規格を元に POSIX 標準規格と比較しながら見ていきたいと思います。
コマンド一覧
-
*
は POSIX で標準化されているコマンドです -
+
は 過去に POSIX で標準化されていたが現在は削除されているコマンドです
コマンドの意味は System V Interface Definition Fourth Edition の Volume 2 または Volume 3 を参照してください。また POSIX で削除されたコマンドの一部は POSIX Rationale for Shell & Utilities でその理由を知ることができます。
BASIC COMMANDS AND UTILITIES
ar * defadm kill * pfmt strchg
awk * df * lfmt pg + strconf
banner + diff3 line + pr * sum +
basename * diff * listusers printf * tail *
cal * dirname * ln * ps * tee *
calendar + du * ls * pwd * test *
cat * echo * mail + red + touch *
cd * ed * mkdir * rm * tr *
chmod * expr * more * rmail true *
cmp * false * mv * rmdir * umask *
col + file * nawk rsh uname *
comm * find * nl * sed * uncompress *
compress * fmt nohup * sh * uniq *
cp * gettxt pack + sleep * unpack +
cpio + grep * page sort * wait *
ctags * head * paste * spell + wc *
cut * iconv * pcat + split * zcat *
date * jsh
基本的なコマンドで見たことがあるようなコマンドばかりです。殆どが POSIX でも標準化されています。OS に依存するものではないため他の環境でも容易に同じように動作させることができたのだと思います。
ADVANCED COMMANDS AND UTILITIES
at * cu + lp * su uustat *
atq dd * lpstat + tabs * uuto +
atrm dircmp + mailx * tar + uux *
batch * ex * mesg * tty * vi *
cancel + gencat * newgrp * uucp * wall +
chgrp * groups news uudecode * who *
chown * iconv * od * uuencode * write *
cron id * passwd uulog +
crontab * join * priocntl uuname +
csplit * logname * stty * uupick +
こちらも見たことがあるようなコマンドが多く POSIX でも標準化されています。atq
や atrm
や cron
などあって然るべきもの本家にはちゃんと定義されていたということがわかります。
ADMINISTERED SYSTEMS COMMANDS AND UTILITIES
acctcms fdp lastlogin pkgparam setmnt
acctcom ffile link * pkgproto setuname
acctcon1 fimage logins pkgrm shutacct
acctcon2 fmtmsg logkeeper pkgtrans srchtxt
acctdisk fsck migration prctmp startup
acctmerg fsdb mkfs prdaily sync
accton fstyp mkmsgs prtacct sysdef
acctprc1 fuser * mknod prtconf timex
acctprc2 fwtmp modadmin pwck turnacct
acctwtmp groupadd monacct removef umount
backup groupdel mount restore unlink *
bkexcept groupmod msgalert rsnotify urestore
bkhistory grpck msglog rsoper ursstatus
bkoper incfile msgrpt rsstat useradd
bkreg init mvdir runacct userdel
bkstatus installf nice * sa1 usermod
chargefee ipcrm * pkgadd sa2 volcopy
ckpacct ipcs * pkgask sacadm whodo
devnm killall pkgchk sadc wtmpfix
diskusg labelit pkginfo sadp zdump
dodisk last pkgmk sar zic
fdisk
システム管理系コマンドです。聞いたことがないようなものが結構ありますが、ディスク管理の fdisk
や mkfs
、パーティションの mount
や unmount
、ユーザー管理の useradd
や groupadd
など、POSIX では標準化されていませんが、通常の利用でなくはならないコマンドもいくつかあります。pkg*
はパッケージ管理ツールのようですね。こういったコマンドも SVID ではちゃんと定義されていたということがわかります。
AUDITING EXTENSION COMMANDS AND UTILITIES
auditcnv auditlog auditoff auditrpt auditset
auditfltr auditmap auditon
監査のためのコマンドのようです。知らないコマンドばかりですが個人的にこういったコマンドを使ったことがないので、よく知られているコマンドかどうか判断できません。しかしこういった監査のコマンドも Unix の機能として考えられていたということがわかります。
ENHANCED SECURITY EXTENSION COMMANDS AND UTILITIES
admalloc defsak getacl lvlprt setacl
adminrole devattr getdev mailcheck tcpio
adminuser devstat lvldelete mldmode tfadmin
chlvl filepriv lvlname putdev
これもよく知らないコマンドばかりですが、名前からすると setacl
/ getacl
はそのまんま ACL 関連のコマンドでしょう。Unix はもう少しセキュリティ関連の拡張機能を備えているべきだったということでしょう。
REMOTE SERVICES COMMANDS AND UTILITIES
chkey keyserv rpcinfo dfmounts newkey
share dfshares rpcbind unshare keylogin
rpcgen
こちらもよくわかりませんが、かろうじて rpc*
は RPC 関連のなにかだというのはわかります。同じコマンドかどうかはわかりませんが macOS でも使えるようです。つまり Unix はリモートサービスのコマンドも備えています。
SOFTWARE DEVELOPMENT COMMANDS AND UTILITIES
admin * delta * lint + rmdel * tsort *
as dis lorder sact * unget *
cc + env * m4 * size val *
cflow * gcore make * strip * what *
chroot + get * nm * time * xargs *
cxref * ld prof truss yacc *
debug lex * prs *
久々に見覚えがあるコマンドが登場しました。ソフトウェア開発用のコマンドですね。xargs
は ADVANCED COMMANDS AND UTILITIES あたりでも良いような気がしますが、開発用コマンドとしての位置づけだったようです。tsort
(topological sort) は sort
の一種として考えられるかもしれないけど使い方難しいだろう(というか使ったことありません)と思っていたのですが、開発用コマンドとして扱われているというのであれば納得です。
TERMINAL INTERFACE COMMANDS AND UTILITIES
captoinfo clear infocmp tic tput *
ターミナル関連のコマンドです。tput
は結構おなじみのコマンドですが、個人的には現実的にメリットが小さく逆に移植性が下がると判断してるので、あえて使わないことにしていたりします。
REMOTE ADMINISTRATION COMMANDS AND UTILITIES
catreq catsend distauth remtab distrpt
pkgcat pkgdel distconf pkgreq pkgsend
pkgtrk pkgput remalias remclean remkill
remadmin remop remstat
さてまたよくわからないコマンドだらけですが、どうやらリモートのシステム管理を行うためのコマンドのようですね。下位で使うネットワークプロトコルはよくわかりませんが、サーバーに接続できている状態でそのサーバーを管理するということはできたようです。
POSIX のみで標準化されているコマンド
今度は逆に POSIX では標準化されているけど SVID では標準化されていないコマンドです。標準化されなかっただけで実際の環境にはインストールされていたのではないかと思っていますが当時のことはよくわかりません。シェルで実装すべきシェルビルトインと、POSIX が追加しすぐに削除される運命にある Batch Utilities は省いています。
Command | First appeared | Command | First appeared | |
---|---|---|---|---|
asa | 1983 System V | man | 1972 Version 2 AT&T UNIX | |
bc | 1975 Version 6 AT&T UNIX | mkfifo | 1994 4.4BSD ? | |
cksum | 1994 4.4BSD ? | patch | 1986 4.3BSD | |
expand | 1979 3BSD | pathchk | ? | |
fold | 1978 1BSD | pax | 1994 4.4BSD ? | |
fort77 | 1992 XPG4 | renice | 1980 4BSD | |
getconf | ? | sccs | 1986 4.3BSD | |
locale | ? | strings | 1979 2BSD | |
localedef | ? | talk | 1983 4.2BSD | |
logger | 1986 4.3BSD | unexpand | 1979 3BSD |
First appeared は wikipedia の List of Unix commands から取ってきています。ほとんどが BSD 由来のコマンドとであることがわかります。SVID にも BSD 由来のコマンド(例 vi
) がいくつかあるので SVID がわざと BSD コマンドを省いていたということにはならないと思います。ただ POSIX では SVID で標準化されてないコマンドでも、実際の環境にはほぼ入っているという理由でこれらも含めたのではないでしょうか。「Unix が持つべきコマンドか」という観点で選んだ SVID と「移植性があるコマンドか?」という観点で選んだ POSIX の違いです。
SVID で定義されたコマンドは必要十分なのか?
SVID にはネットワークに関するコマンド(ifconfig
や route
コマンド等)がありません。それは必要ないと思っていたからではなくタイミングの問題だと思っています。ネットワーク通信をするのに必須なソケット API は 1983 年 4.2BSD で実装されました。また ifconfig
や route
コマンドは 4.2BSD に含まれています。一方 AT&T の Unix では BSD のソケット API がベンダーの手によって System III (1982) に移植されていたようですが、System V Release 4 (1989) までは搭載されず、代わりに AT&T で開発した STREAMS の方を推奨していたようです。おそらくこのせいでネットワーク関連のコマンドが SVID では標準化が追いつかなかったのだと思います。
The Design and Implementation of the 4.4BSD Operating System より
Another benefit is that the new interface is highly portable. Shortly after a test release was available from Berkeley, the socket interface had been ported to System III by a UNIX vendor (although AT&T did not support the socket interface until the release of System V Release 4, deciding instead to use the Eighth Edition stream mechanism). The socket interface was also ported to run in many Ethernet boards by vendors, such as Excelan and Interlan, that were selling into the PC market, where the machines were too small to run networking in the main processor. More recently, the socket interface was used as the basis for Microsoft’s Winsock networking interface for Windows.
もう一つの例としては sudo
コマンドがあります。このコマンドはセキュリティをより現実的なものとするために必須と言っても良いもので実際に広く利用されています(例外として OpenBSD ではよりセキュリティが強化された doas
が使われています)。su
コマンドは SVID で標準化されていますが sudo
コマンドはありません。その理由は sudo
がいつ作られたか?を調べることでわかります。公式サイトの A Brief History of Sudo によると sudo
が作られたのは 1980 年頃らしいですが、一般公開(ニュースグループに投稿)されたのは 1985 年 12 月です。最初の SVID1 が作られたは 1985 年の春ですので到底間に合うわけがありません。最後の SVID4 が登場する 1995 年までの間に System V に移植された可能性はありますが、リリースしたばかりですしその後 sudoers 形式の強化を含む修正が行われており SVID に含めるまでもないと判断しても不思議ではないでしょう。あとどうでもいいんですけど sudo の公式サイト始めて見たんですけど、須藤さんのマスコットって食パンのきぐるみなんですね。なんか某ナシ型のきぐるみとコラボしたら面白いんじゃないかなと・・・いやなんでもないです。
それからコマンドが不十分なのは POSIX も同じです。30 年前に作られてからほとんど追加が行われていないので、現在の常識では必須と言えるようなものはコマンドされていません。というのを付け加えておきます。
さいごに
ということで AT&T が考えた「Unix に必要なコマンドとはなにか?」という話でした。SVID には POSIX で規定されているものよりも遥かに多くのコマンドが定義されていたということがわかります。
POSIX は SVID に比べて多くのコマンドが足りません。もちろんこれは POSIX が劣っているという意味ではありません。単に方針の違いで System V と BSD で移植性がなかったから、もしくは POSIX で定義すべきようなコマンドではなかったという理由で定義されなかったと言うだけのことです。例えばライブラリやデータベース、ミドルウェアのようなものは OS とのインターフェースではないので最初から POSIX の対象外です。POSIX には Unix に必要なコマンド(もしくはソフトウェア開発に必要なコマンド)がすべて定義されてないという事実から言えることは POSIX で規定されているコマンドだけを使ってソフトウェアを開発するのはベストプラクティスではないということ。はっきりわかんだね。
The following areas are outside of the scope of POSIX.1-2017:
- Graphics interfaces
- Database management system interfaces
- Record I/O considerations
- Object or binary code portability
- System configuration and resource availability
POSIX.1-2017 describes the external characteristics and facilities that are of importance to application developers, rather than the internal construction techniques employed to achieve these capabilities. Special emphasis is placed on those functions and facilities that are needed in a wide variety of commercial applications.
またもう一つ重要なのは POSIX が規定しているのは「移植性がないコマンドの中からの抜粋」であるということです。例えば git
や jq
などの実装しているベンダーが一つしか無いものは POSIX では規定されません(規定する意味がない)。実装しているベンダーが一つしか無いのにいったい何を見て「どこでも同じように動く」オプションを羅列すれば良いのでしょうか?すべてのオプションを羅列すれば良いのでしょうか?
例えば wget
コマンドは元々 GNU が開発したコマンドですが、今は BusyBox も実装しています(他にも ToyBox が実装していますがまだ開発中です)。もし GNU だけが開発している状態であれば、すべての機能がどこでも同じように動くのは明らかですから、これを POSIX で標準化する意味はありません。しかし実装が 3 つにもなれば特定の実装でしか動かないオプションもあるでしょう。そういう段階になれば「共通で使えるオプション」を標準化する意味が生まれます。POSIX で標準化されるというのはこういう事です。
SVID は Unix に必要なコマンドが記載されていますが POSIX はそうではありません。POSIX には複数のベンダーで共通しているコマンドが記載されています。と言えば聞こえは良いですが、実際には複数のベンダーが同じ名前でコマンドを実装しており移植性に問題があるからこそ記載されているのです。つまり POSIX コマンドは「どこでも同じように動くコマンド」ではなくて逆に「どこでも同じようには動かないコマンド」 なのです。これだけははっきりと真実を伝えたかった。