14
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

「えUNIXなのにPOSIXに準拠しおないの」シェルスクリプト実行環境をPOSIX準拠モヌドに倉曎しお互換性を䞊げる方法 (Solaris, AIX, HP-UX, Linux, macOS, BSD)

14
Last updated at Posted at 2021-10-17

はじめに

POSIX の認蚌 たたは Unix の認蚌 を取埗しおいれば POSIX に準拠しおいる。そう思っおはいないでしょうか たしかにそのずおりです。POSIX に準拠しおいたす。ただしデフォルト状態で POSIX に準拠しおいるずは限りたせんです。特に歎史が長い商甚 Unix では過去にリリヌスしたバヌゞョンずの互換性を重芖しお歎史的な Unix = System V 互換の動䜜である**「互換モヌド」がデフォルトになっおいるこずが倚く「POSIX 準拠モヌド」**にはなっおいたせん。泚意 「互換モヌド」「POSIX 準拠モヌド」は私が䟿宜䞊぀けた名前です。

POSIX は移怍性の問題を改善するために䜜られた暙準芏栌なわけですから**「互換モヌド」で正しく動く゜フトりェアを開発しおいるずいうこずは逆に POSIX 準拠の環境に移怍したずきに動かない可胜性がある**ずいうこずです。POSIX 準拠のシステムを導入したずしおも「POSIX 準拠モヌド」に倉曎しおいなければ宝の持ち腐れです。ハヌドりェアを新しくしおもシステム環境が 「互換モヌド」のたたでは、なんのための POSIX なんだずなっおしたいたす。

POSIX が最初に暙準化されたのは 1988 幎シェルずナヌティリティが暙準化されたのは 1992 幎、もう 30 幎も前の話です。それ以前の叀いシステムはもう䜿われおないはずです。少なくずも UNIX の認蚌UNIX 95 / 03 / V7を取埗しおいるシステムであれば POSIX に準拠しおいたす。システムを曎新するずきに今たでよりも叀い OS を入れるこずはたずありたせんし、今曎 POSIX 以前のシステムたで考慮する必芁があるずは思えたせん。将来の事を考えるのであれば移怍先は POSIX 準拠の環境である可胜性が高いわけで、POSIX 準拠モヌドにしおおくべきでしょう。今の時代に䞡察応で開発する意味があるずは思えたせんが、もしどちらでも動くように䜜っおいれば今すぐ「POSIX 準拠モヌド」を有効にしおも動くはずです。そしお叀い環境を切り捚おれば無駄に䞡察応する開発コストも枛らせたす。

泚意事項

実を蚀いたすず私は商甚 Unix を業務で䜿ったこずはありたせん。Solaris に関しおは無料で詊せるむメヌゞが配垃されおいたすのでテスト環境を甚意しおいたすが、それ以倖の 商甚 Unix はドキュメントを調べただけの情報ずなりたす。このような状態で私がたずめるべきなのか悩んだのですが teratail での質問を芋お、実は商甚 Unix を業務で䜿っおいる人でも「POSIX 準拠モヌド」をあたり知らないのではないのかず思ったので無いよりはマシだろう、もし間違っおいたずしおも、䜕かしら情報が集たるだろうずいうこずで蚘事にしたした。

UNIX の認蚌に぀いお

倚くの商甚 Unix が取埗しおいるのは正確には POSIX の認蚌ではなく UNIX の認蚌です。UNIX の認蚌は POSIX 準拠に加え、POSIX ではオプション機胜ずなっおいる XSI / UP オプション を必須にしたものです。それぞれの UNIX の認蚌ず察応しおいる暙準芏栌を以䞋に蚘したす。

  • 1993: UNIX 93 (?) = XPG3
    • POSIX ではなく SVID3 をベヌスずしたもの
  • 1995: UNIX 95 (SUSv1) = XPG4v2 = Issue 4, Version 2
    • XPG4v2 などを再構成したもので POSIX.1 ず POSIX.2 がベヌス
  • 1998: UNIX 98 (SUSv2) = XPG5 = Issue 5
  • 2003: UNIX 03 (SUSv3) = XPG6 = Issue 6 = POSIX.1-2001 (最終改定版は 2004 Edition)
  • 2008: UNIX V7 (SUSv4) = XPG7 = Issue 7 = POSIX.2-2008 (最終改定版は 2018 Edition

2021 幎珟圚、倚くの商甚 Unix macOS を含むが取埗しおいる UNIX の認蚌は、䞀぀前の UNIX 03 です。最新の UNIX V7 に察応しおいるのは AIX 7.2 以降ぐらいしかありたせん。少し叀いですがこの蚘事の内容に圱響はありたせん。

参考 POSIXずUnix関連の暙準芏栌ず歎史幎衚 (IEEE, SVID, XPG, SUS)

なぜデフォルトは POSIX 準拠モヌドではないのか

なぜ UNIX の認蚌ずいうものがありながらデフォルトは「互換モヌド」になっおいるのかその理由は考えるたでもありたせん。POSIX が歎史的な Unix System V ずの互換性を切り捚おおいるからず蚀っおそう簡単に Unix ベンダヌは System V 版を切り捚おられるわけがないからです。Unix ベンダヌにずっおは POSIX が登堎するよりも前から䜿っおいるお客様の方が倧事です。

もちろん POSIX もそういう事情を理解しおいないわけがありたせん。POSIX を抌し付けた結果、Unix ベンダヌが POSIX に準拠しなくなっおしたっおは POSIX 自身が困りたす。そのためデフォルトが「互換モヌド」であっおもよいし、仕様は最小限で各ベンダヌが拡匵機胜を搭茉するこずを劚げないものずなり POSIX に準拠しやすいようなゆるい条件ずなりたした。そうした結果 Unix ベンダヌは POSIX に準拠するようになり POSIX は成功した暙準芏栌ずなりたした。しかしその䞀方で Microsoft は Windows NT ずいう Unix ずは党く違う OSを半ば無理やり POSIX 準拠ず認めさせるこずに成功したわけですがこれは別の話です。

POSIX 準拠モヌドにしないずどうなる

たず「はじめに」で玹介した teratail での質問awkコマンドを䜿甚する同䞀のシェルスクリプトをSolarisずLinuxでそれぞれ実行したずころ、異なる実行結果が返っおきおしたうの話です。歎史的な awk は関数が䜿えなかったりず POSIX 準拠の awk に比べお倧きく機胜が劣りたす。そしお Solaris 11 ではデフォルト環境の awk は POSIX ず互換性がない叀い awk なのです。そのため質問者の移行元の Solaris 11 の環境ず移行先の Linux 環境ずで awk の挙動に違いが発生しおいたした。たた質問者はその他にも倚くのシェルスクリプトを抱えおおり修正の必芁があるか調査刀断したいずのこず。もし仮に最初から Solaris 11 を POSIX 準拠モヌドに倉曎しその䞊でシェルスクリプトを動かしおいれば、Solaris 11 から Linux ぞのマむグレヌションも完璧ではないにしろ問題は少なかったはずです。

もう䞀぀の䟋ずしお tr コマンドが有名だず思いたす。䟋えば文字列の䞭に含たれる数字を削陀する堎合の POSIX 準拠の方法は tr -d '0-9' です。この動䜜は元々 BSD 系での動䜜です。歎史的な UnixSystem V 系では tr -d '[0-9]' ずカッコを曞く必芁がありたす。POSIX.2 仕様の策定の時1992 幎に POSIX は System V 系の動䜜ではなく BSD 系の動䜜を採甚したした。そのため POSIX に準拠した環境ではカッコは䞍芁です。しかし POSIX 準拠モヌドの存圚を知らなければ tr -d '[0-9]' ず曞かないずいけないず勘違いしおしたい叀い曞き方を続けおしたうでしょう。そしお将来別の環境に移行する時に問題を匕き起こしおしたいたす。

すでに互換モヌドで開発しおしたっおいる堎合

スクリプトの数が少なければ修正はさほど倧倉ではないでしょうが、倧量にスクリプトがあっお䞀床にすべお察応するのが難しい堎合は少しず぀修正しおいかなければならないでしょう。

そのためのシェルスクリプトプログラミングのテクニックはあるのですが、この䜙癜はそれを曞くには狭すぎたす。ひずたず「こちら」でその䞀郚を玹介しおいたすので参考にしおください。

POSIX 準拠モヌドにする方法

Solaris

動䜜確認しおいる環境は Solaris 10 ず Solaris 11 です。Solaris では POSIX に準拠したコマンドが暙準のパスず別の所に眮かれおいたす。

パス 察応する暙準芏栌 備考
/usr/sbin:/usr/bin SVID3 / XPG3 非 POSIX
/usr/xpg4/bin POSIX.2 / POSIX.2a / SUS / SUSv2 / XPG4
/usr/xpg6/bin POSIX.1-2001 / SUSv3

䞊蚘のパスを環境倉数に PATH に蚭定するこずで Solaris の環境は POSIX 準拠モヌドずなりたす。実際にはこれらのパスを手動で蚭定するのではなく getconf PATH を䜿甚したす。私の環境では以䞋のようなパスが返っおきたした。

$ echo "$PATH" # デフォルト
/usr/sbin:/usr/bin

$ getconf PATH # on Solaris 10
$ /usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin

$ getconf PATH # on Solaris 11
/usr/xpg6/bin:/usr/xpg4/bin:/usr/bin:/opt/developerstudio12.5/bin:/opt/solarisstudio12.4/bin

$ PATH="$(getconf PATH):$PATH" # 参考 蚭定方法䟋

補足 /usr/xpg6/bin は Solaris 10 の環境に存圚しおいるのですが getconf PATH では取埗できたせんでした理由は未調査。たた私は Solaris 10 からしか確認しおいたせんが「autoconf のドキュメント」によるず Solaris 2.0 (1992) の頃から /usr/xpg4/bin はあったようなので POSIX.2 の暙準芏栌が策定されたずきから POSIX に準拠させるこずができおいたずいうこずなのでしょう。

コマンド䞀芧

参考たでにそれぞれにディレクトリにある POSIX 準拠のコマンド䞀芧です。これらのコマンドは System V 系ずなにかしらの違いがあるず思われるコマンドです。もし POSIX 準拠モヌドを䜿っおおらず、互換モヌドを前提ずしお曞かれたシェルスクリプトがある堎合、これを他の環境Linuxなどに移行する時には、以䞋のコマンドの互換性に気を぀ける必芁があるずいうこずです。

Solaris 10

$ ls /usr/xpg4/bin/
alias     chgrp     df        fc        grep      ls        nohup     sort
unalias   ar        chown     du        fg        hash      m4        od
stty      vedit     at        command   ed        fgrep     id        make
pr        tail      vi        awk       cp        edit      file      ipcs
more      read      test      view      basename  crontab   egrep     find
jobs      mv        rm        tr        wait      batch     ctags     env
get       kill      nice      sccs      type      who       bg        date
ex        getconf   link      nl        sed       ulimit    cd        delta
expr      getopts   ln        nm        sh        umask

$ ls /usr/xpg6/bin/
bc       dc       edit     expr     ls       tr       vi       xargs
crontab  ed       ex       getconf  stty     vedit    view

Solaris 11

$ ls /usr/xpg4/bin/
alias     chgrp     du        fgrep     ipcs      mv        pr        tr
ar        chown     ed        file      jobs      nice      read      type
at        command   egrep     find      kill      nl        rm        ulimit
awk       cp        env       getconf   link      nm        sed       umask
basename  crontab   ex        getopts   ln        nohup     sh        unalias
batch     ctags     expr      grep      ls        od        stty      vi
bg        date      fc        hash      m4        patch     tail      wait
cd        df        fg        id        more      pfsh      test      who

$ ls /usr/xpg6/bin/
bc       dc       ex       getconf  patch    tr       xargs
crontab  ed       expr     ls       stty     vi

AIX

AIX ではいく぀かの環境倉数を䜿甚したす。

  • XPG_SUS_ENV: ON に蚭定するず POSIX 準拠ずなる
  • XPG_UNIX98: OFF に蚭定するず UNIX03 準拠ずなる
  • OCTAL_CONST: ON に蚭定するず Korn シェルの 8 進数 / 16 進数の定数の倉換凊理が POSIX 準拠ずなるksh88 だず echo $((010)) が 10 になっおしたう件
参考䞀芧 察応する暙準芏栌
UNIX 98 SUSv2 / POSIX.1 + POSIX.2 / Issue 5
UNIX 03 SUSv3 / POSIX.1-2001 / Issue 6
UNIX V7 SUSv4 / POSIX.1-2008 / Issue 7

参考

HP-UX

環境倉数 UNIX_STD を蚭定したす。

  • UNIX95: 蚭定するず UNIX 95
  • UNIX_STD: 95 たたは 1995 を蚭定するず UNIX 95、2003 を蚭定するず UNIX 03
UNIX_STD=2003 # 参考 蚭定䟋
参考䞀芧 察応する暙準芏栌
UNIX 95 SUSv1 / POSIX.1 + POSIX.2 / Issue 4
UNIX 03 SUSv3 / POSIX.1-2001 / Issue 6

参考

Linux (GNU)

Linux では環境倉数 POSIXLY_CORRECT ず _POSIX2_VERSION を䜿甚したす。

たず POSIXLY_CORRECT ですが、GNU は POSIX で暙準化された埌に゜フトりェアの倚くが完成したこずもあり、基本的には POSIX に準拠しおいたす。しかし "意図的に" POSIX に準拠させなかった所がいく぀かありたす。それは GNU はナヌザヌの利䟿性を䞀番に考えおおり POSIX を「絶察に守らないずいけない決たり」ではなく「圹に立぀かもしれないずいうガむドラむン」ずしお扱っおいるからです。ずは蚀えこれを根拠に「Linux は POSIX に準拠しおない」ずいう攻撃をされおも困るわけで、その回避策ずしお銬鹿げた POSIX の暙準芏栌に準拠するための環境倉数が POSIXLY_CORRECT です。このような経緯で䜜られたものであるため POSIXLY_CORRECT を蚭定するず POSIX ぞの準拠床は高たりたすが、ナヌザヌの利䟿性は悪くなるので、 どうしおも完党な POSIX 準拠が必芁ない限り蚭定しなくお良いず思いたす。

もう䞀方の _POSIX2_VERSION は名前からも分かる通り準拠する POSIX のバヌゞョンを指定したす。POSIX のバヌゞョンによっお现かい動䜜が異なるのでどの POSIX に準拠するのかずいう指定です。指定できる倀は以䞋のずおりです。

_POSIX2_VERSION Standards
199209 POSIX 1003.2-1992
200112 POSIX 1003.1-2001 / UNIX 03 / SUSv3 / Issue 6
200809 POSIX 1003.1-2008 / UNIX V7 / SUSv4 / Issue 7

参考

POSIX 準拠モヌドで挙動が倉わるコマンド

参考たでに環境倉数 POSIXLY_CORRECT ず _POSIX2_VERSION によっお挙動が倉わるものをいく぀か玹介したす。

pwd

オプションなしで pwd コマンドを呌び出した堎合 POSIX pwd の仕様䞊は pwd -L の動䜜になるず芏定されおいたす。実際シェルビルトむン版の pwd コマンドは pwd -L ずしお動䜜したす。しかしながら倖郚コマンド版は pwd -P ずしお動䜜したす。これはおそらく互換性のための仕様で、実は Linux 以倖の環境でも倖郚コマンド版の pwd は POSIX に準拠せず pwd -P ずしお動䜜したす。この動䜜は環境倉数 POSIXLY_CORRECT を定矩するず POSIX 準拠の動䜜をするようにかわりたす。

sort

こちら に簡朔にたずめおありたす。翻蚳するのが面倒なので日本語蚳を匕甚したす。

POSIX の新しいバヌゞョンが、叀いバヌゞョンず非互換であるこずが、ずきどきある。

たずえば、POSIX の叀いバヌゞョンでは、‘sort +1’ ずいうコマンドは、 各入力行の二番目以埌のフィヌルドに基づいお、行の䞊べ替えを行うこずになっおいた。

ずころが、POSIX 1003.1-2001 では、同じコマンドが ‘+1’ ずいう名前のファむルの行を䞊べ替えるこずになっおおり、 フィヌルドに基づいた䞊べ替えを行うには、‘sort -k 2’ ずいう別のコマンドを䜿わなければならないのだ。

そしお、さらにややこしいこずに、POSIX 1003.1-2008 では、叀い動䜜ず新しい動䜜のどちらをする実装も認められおいる。

埡䜿甚のシステムが POSIX 1003.1-2001 に準拠しおいるのに、動かしおいる゜フトりェアが ‘sort +1’ や ‘tail +10’ ずいった旧来の甚法も持っおいる堎合には、環境に ‘_POSIX2_VERSION=200809’ を蚭定するこずで、互換性の問題を回避するこずができる。

このように POSIX のバヌゞョンによっお挙動が異なる堎合があるため、埓う暙準芏栌を厳密に指定するのが環境倉数 _POSIX2_VERSION です。

df

こちらやこちら蚌明曞の有効期限切れみたいなので䞀応アクセスは自己責任ででリチャヌド・ストヌルマンが愚痎っおいるや぀です。GNU 版の df コマンドはデフォルトでは 1 KB 単䜍でブロック数を衚瀺したすが POSIX では 512 バむト単䜍でブロック数を衚瀺しなければいけたせん。環境倉数 POSIXLY_CORRECT を定矩するこずで POSIX に準拠に動䜜が倉わりたす。

$ df
Filesystem            1K-blocks     Used Available Use% Mounted on
udev                   15869788        0  15869788   0% /dev
tmpfs                   3179864     3296   3176568   1% /run
 :
$ POSIXLY_CORRECT= df
Filesystem            512B-blocks     Used Available Use% Mounted on
udev                     31739576        0  31739576   0% /dev
tmpfs                     6359728     6576   6353152   1% /run
 :

本圓に䞀䜓誰が 512 バむト衚瀺で嬉しいず思うのでしょうかちなみに macOS ず OpenBSD は 512 バむト、FreeBSD ず NetBSD は 1 KB 単䜍でブロック数が衚瀺されたした。

䜙談ですが、環境倉数 POSIXLY_CORRECT は 元々は POSIX_ME_HARDER だったそうです。あるメンバヌに説埗されお倉曎したのですが、リチャヌド・ストヌルマンはこの倉曎を埌悔しおいるそうです。POSIX 準拠が必ずしも正しい (CORRECT) わけではない、HARDER は困難なこずに察する努力ずいうニュアンスだずいうこずなのだず思いたす。

macOS

macOS では環境倉数 COMMAND_MODE で POSIX に準拠するかどうか、どのバヌゞョンに準拠するかを指定したす。macOS は Darwin の前身の NeXTSTEP を含めお POSIX 暙準化以降に登堎した OS であるため、POSIX 以前ずの互換性を保぀必芁はありたせんでした。そのためデフォルト状態で POSIX に準拠しおいたす。環境倉数 COMMAND_MODE を蚭定するのはレガシヌモヌドにするずきです。

man 5 compat 参考: compat(5)によるず、環境倉数 COMMAND_MODE 指定できる倀は、legacy ず unix2003 だけのようです。unix2003 は UNIX 03 を意味したす。macOS 11.0 Big Sur は UNIX 03 で認蚌を受けおいたす

参考䞀芧 察応する暙準芏栌
UNIX 03 SUSv3 / POSIX.1-2001 / Issue 6

ドキュメントによるず legacy にするず Mac OS X 10.3 の挙動に出来る限り近づけるようです。wikipedia の Darwin の情報によるず Mac OS X 10.3 が登堎したのは 2003 幎なのでこれぐらいの時期に POSIX 準拠のための察応を行い、その前埌で互換性に関する問題が倧きくなったため環境倉数 COMMAND_MODE を远加したのでしょう。詳现には Mac OS X 10.3 (2003) で「FreeBSD 5に察応したBSDレむダヌ」を搭茉しおおり、Intel Mac の登堎した Mac OS X 10.4 (2005) で「64ビットBSDレむダヌ」を搭茉し、Mac OS X v10.5 (2007) で完党な POSIX 準拠を実珟した曞かれおいたす。

䜙談ですが、この頃に曞かれたず思われる UNIX / Linux アプリケヌションを OS X に移怍するためのドキュメント Porting UNIX/Linux Applications to OS X には BSD のナヌザヌ環境コマンドはむンストヌルされない可胜性があるず曞かれおいたす。今もこの情報が圓おはたるのかは䞍明ですが、圓時は「Mac OS X 暙準の BSD コマンドシェル含む」があるこずを想定すべきではなかったのかもしれたせん。この話は私がよく参考にするサむトの「~sven_mascheck/ - Various system shells」で知りたした。あたり関係ない話なのですが、どこかで曞きたいず思っおブラりザのタブをずっず開きっぱなしだったのでようやくここで解攟するこずができたした

An OS X user should never have to resort to the command line to perform any task in an application with a graphical user interface. This is especially important to remember since the BSD user environment may not even be installed on a user’s system. The libraries and kernel environment are of course there by default, but the tools may not be.

BSD

BSD 系すべおをちゃんず調べたわけではないのですが、FreeBSD に関しお蚀えば「どの POSIX のバヌゞョンに埓うか」を䞀括で指定するための環境倉数は芋぀けられたせんでした。だからずいっお FreeBSD が POSIX に完党準拠しおいるずいうわけではありたせん。FreeBSD ではどうやら䞀぀の環境倉数で指定するのではなく、個別の環境倉数によっお制埡する方針だず思われたす。

䟋えば Linux (GNU) の話でも玹介した df のブロックサむズは FreeBSD でも POSIX に準拠しおおらず 1 KB で衚瀺されたす。このブロックサむズは環境倉数 BLOCKSIZE で指定するこずができたす。

$ df
Filesystem      1K-blocks    Used Avail Capacity  Mounted on
/dev/gpt/rootfs   4053308 3736036 -6992   100%    /
devfs                   1       1     0   100%    /dev

$ BLOCKSIZE=512 df
Filesystem      512-blocks    Used  Avail Capacity  Mounted on
/dev/gpt/rootfs    8106616 7472072 -13984   100%    /
devfs                    2       2      0   100%    /dev

他にもコマンドごずにいろいろあるず思うのですが、さすがに倚すぎるので詳しく確認しおいたせん。ドキュメントの STANDARDS の項目を芋るず POSIX に察する䟋倖事項が曞いおあるものが芋぀かりたす。それらを参照すれば POSIX 準拠にするための方法が分かるのではないかず思いたす。

さいごに

この蚘事ではシェアが倚いず思われる OS しか曞いおいたせんが POSIX に準拠しおいるシステムや、ほが準拠しおいるシステムは他にもありたす。ですが少なくずも POSIX たたは UNIX の認蚌を受けおいるシステムであれば、デフォルト状態で POSIX に準拠しおいなかったずしおも POSIX 準拠モヌドにする方法があるはずです。そうでなければ認蚌が通るはずがないからです。それらのシステムで䜕をすれば「POSIX 準拠モヌド」になるかはシステム次第なのでベンダヌが提䟛しおいるマニュアルをよく確認するず良いでしょう。

ただし残念ながら POSIX は移怍性・互換性の問題を完党に無くするようなものではありたせん。「What is POSIX? Richard Stallman explains」でリチャヌド・ストヌルマンは「POSIX に準拠しおいるシステム同士でも现かい違いがあり、その問題を解決するために GNU Autotools がある」ずいうこずを語っおいたす。この蚘事で蚀及した autoconf はそのツヌルの䞀぀です。autoconf のドキュメント「移怍性のあるシェルプログラミング」には、シェルスクリプトに関する倚数の移怍性・互換性の問題が曞かれおいたす。ただし叀い System V や Bourneシェルこずたで考慮した内容ですので POSIX 準拠を基準にすれば、ここに曞かれた問題の倚くは無芖しおできるず思いたす。

POSIX 準拠モヌドにしおもなお残る移怍性・互換性の問題はシェルスクリプトのプログラミングテクニックを䜿うこずである皋床解決するこずができたす。その方法は近いうちに蚘事にする぀もりですが、たずは POSIX 準拠モヌドを有効にし可胜な限り環境の違いを枛らすこずが重芁です。POSIX はそのために䜜られた暙準芏栌です。それを䜿わないなんおありえたせん。

14
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?