if い fi t$server" ] ; then echO $server if [ -f /usr/etc/in. routed ] ; ースーバー then ーⅡ routed' In. routed; fi echO echo # le f0110Wi れ g wi11 mount /tmp if set up in /etc/fstab. If you want to use # the anonymous memory based file system, have fstab entry of the fo ェ : /tmp tmp 0 0 swap # Make sure that option ・ IWFS is configured in the kernel # (consult the System and Network Administration Manua1) . intr if [ fi if [ fi tai 1 + 2 dmesg ー /tmp —a mount —vat nfs echO ー取 ' starting additional services : —f /usr/etc/ in. named —a —f /etc/named. boot ] ; in. named ; echO ー ' named ) —f /usr/etc/biod ] ; then # mount then biod 4 ; echo —n ' biod' echO ' grep SunOS ー tail ー 1 ー sed —e "s/-. *SunOS/Sun0S/'t >/tmp/tl /etc/motd >>/tmp/tl mv /tmp/tl /etc/motd chmod 666 /etc/motd # syslogd doesn 't belong here, but needs to be started before the others. # lt needs tO be started after NIS , though, so it can find the "syslog' # udp service. if [ -f /usr/etc/syslogd ] ; then echO ' starting system 10 er ' nn -f /dev/ 10g syslogd # Defau1t is to not do a savecore #mkdir —p /var/ crash/ ( hostname ech0 —n 'checking for crash dump. #intr /var,/crash/ 'hostname if fi if fi if fi if fi if fi if fi if fi [ -f /dev/sky ] ; then skyrc /usr/lib/sky. ucode [ -f /dev/fpa ] ; then /usr/etc/fpa/fpa—download [ -f /dev/fpa ] ; then /usr/etc/fpa/fparel [ -f /usr/etc/gpconf ig ] ; then /usr/etc/gpconf ig -f -b [ —f /dev/di albox ] ; then dbconf ig /dev/di albox [ -f /usr/etc/auditd ] ; then echO —n 'startlng 10C 訌 daemons: auditd ; echO ーれ ' auditd' [ -f /usr/lib/sendmail -a —f /etc/sendmail. cf ] ; then ( cd /var/spool /mqueue ; —f 瓩 * If * ) /usr/l ib/sendmail —bd —qlh ; echo ーⅡ ' sendmail ' UNIX MAGAZINE 1991.6 ユーサーへの道 2 35
' start ing network daemons : ( currently) i s a real performance pig for systems with 1 imited memory. -f /usr/etc/ in. rwh0d ] ; then # rwhod echO —n if [ fi if [ fi fi #f i in. rwhod; —f /usr/etc/ inetd ] ; then inetd; echo ーれ ' rwhod' echO —n ' inetd' if [ -f /usr/lib/lpd ] ; then m -f /dev/printer / v 矼 / SP001 / 1 .. lock /usr/l ib/lpd ; echO ーⅡ echO ' date fi —f /usr/nserve/loc. passwd /usr/nserve/loc. passwd. dummy if [ —f /usr/nserve/loc. passwd. dummy ] ; then /usr/bin/dorfs start ; ech0 ' done. fi echO > /usr/nserve/loc. passwd. dummy echO ー > /usr/nserve/loc. passwd if [ ! -f /usr/nserve/loc ・ passwd ] ; then echO ーⅡ starting rfs : #if [ —f /usr/nserve/rfmaster ] ; then ◇ rc 」 oc 引の例 exit 0 @( # ) rc. 10C 1.111 90 / 01 / 03 SMI; from UCB 4.3 # hostname now set in rc . bOOt domainname ( cat /etc/unimag PATH=/bin : /usr/bin : /usr/etc : /usr/ucb ; export F)AIY if if fi if fi if fi if fi echO —n ) starting rpc 田 ld net services : [ —f /usr/et c/portmap ] ; then echO —n ' portmap portmap ; [ —f /usr/etc/ypserv -a —d / v 矼 / / ( domaimame echO —n ypserv ' ypserv ; Master NIS server runs the X ト daemon then ypxfrd; -d / v 矼 / ] ; then ech0 ーれ ' ypxfrd' if [ —f /etc/security/passwd. adjunct ] ; then ypbind ¯s ; else ypbind; fi ech0 —n ' ypbind' ech0 —n ' ypbind' [ —f /usr/etc/keyserv ] ; then ech0 —n ' keyserv ' keyserv; ech0 —n ' ypupdated ) rpc ・ ypupdated; [ —f /usr/etc/rpc. ypupdated -a —d / v 矼 / / 。 domainname ( ] ; then # set the netmask from N IS if running , or /etc/netmasks for a11 ether interf aces ifconfig —a netmask + broadcast 133.1.12.255 > /dev/null # If we are a diskless client , synchronize time—of—day with the server. # E1se , if applicable , r 町 1 the router daemon. N0te that for better # perfomance , we don't enable the router daemon for diskless clients. # At the same time , teminate the currently printing 1ine (for prettiness) . 34 server= grep UNIX MAGAZINE 1991.6
if [ fi if [ elif else fi date ースーバー # Make sure ld. so. cache is removed (rc. single may not invoked # when going from multi—user mode to single-user then back to multi—user) ¯a ¯P -f /etc/ld. so. cache ] ; then # Carefu11y delete ld. so cache in case it is corrupted mv /etc/ld. SO. cache /etc/ld. so. cache— /etc/ld. SO. cache— —r /fastboot ] ; then —f /fastboot [ $lx = autobootx ] ; then echO Automatic reboot in progress. echo Mu1t iuser startup in progress. # attempt to rationally recover the passwd file if needed if [ -s /etc/ptmp ] ; then if [ -s /etc/passwd ] ; then ls ー 1 /etc/passwd /etc/ptmp nn —f /etc/ptmp # should rea11y remove the shorter ech0 'passwd file recovered from ptmp' mv /etc/ptmp /etc/passwd fi elif [ -r /etc/ptmp ] ; then ech0 'removlng passwd lock file ' rm -f /etc/ptmp fi intr mount —at 4.2 intr quotacheck quotaon —a /bin/ps -U rm —f /et c/nologin echO —n ' checking quotas : echO ) done . if [ -f /dev/ttypO ] ; then chown root /dev/tty [pqrs] * chmod 666 /dev/tty Cpqrs] * fi /usr/etc/ttysoftcar —a > /dev/null 2 > & 1 sh /etc/rc. 10Ca1 swapon —a ()d /tmp ; /usr/lib/expreserve -a) ()d /tmp; rm -f update ; nn -f /var/sp001/cron/FIFO cron ; # accounting, ech0 preserv ing editor f i les echO echO echO echO nn —f LCK . * ( cd /var/spool/uucp if [ -d /var/spool/uucp ] ; then #/usr/l ib/acct/startup accounting is 0ff by default. if [ -d /usr/lib/uucp ] ; then clearing /tmp ーⅡ ーⅡ ' standard daemons : ) update' cron ' su uucp —c /usr/lib/uucp/uusched & \ echO ーⅡ uucp fi) fi UNIX MAGAZINE 1991.6 ユーサーへの道 2 33
if [ fi # if fi # if if [ fi —d /tftpboot —a —f /tftpboot/sun2.bb ] ; then ndbootd; echO —n ' ndbootd' /etc/exports fi1e exists become nfs server if [ -f /etc/exports ] ; then > /etc/xtab exportf s —a nfsd 8 & echo —n ) nfsd' if [ -f /etc/security/passwd. adJunct ] ; then # Warning! Turning on port checking may deny access t0 # 01der versions (pre—3.0 ) 0f NFS clients. rpc. mountd ー adb —w /vmunix /dev/kmem >/dev/null 2 > & 1 echO " nfs—portmon/W 1 " rpc . mountd ¯n else fi /tftpboot exi sts become a bOOt server # start fi fi # start fi # start if [ —f fi fi —d /tftpboot ] ; then echo ーれ ) rarpd' , \ rpc. bootparamd up status monitor and locking daemon if present if [ —f /usr/etc/rpc. statd ] ; then c. statd & echo —n ' statd ' if [ —f /usr/etc/rpc. lockd ] ; then echo ーⅡ ' lockd' rpc. lockd & up authentication daemon if present and if adJunct file exists if [ —f /usr/etc/rpc. pwdauthd —a —f /etc/security/passwd. adjunct ] ; then rpc ・ pwdauthd & up the automounter /usr/etc/automount ] ; automount & & echO —n # Bui1d the link—editor fast directory cache. if [ -f /usr/etc/ldconfig ] ; ech0 ーれ ' pwdauthd' then automount ' echO ' then ldconfig; echO "link¯editor directory cache" 電源を切るときの注意 電源を切るのは、計算機を移動させるときなどにつきも のの作業です。、、〇 x 時以降はかならす切らなければならな いクと決められているところもあるでしよう。一方では、 24 時間年中無休で動かしているところもあります。そんな に長い時間動かし続けて問題はないのでしようか。はい、 UNIX は疲れることを知りませんから大丈夫です。むし ろ、立ち上げる時間がかからないぶん便利とさえいえます。 36 しかし、そのまま放っておくと何が起こるか分かりません。 たとえば、なんらかの理由でデーモンが死んでいたり、日 。毎日電源を入れなおす場合と比べると、 付が狂ったり・・ このような注意が必要になります。電気代もかかりますし でも、計算機がつねに動いていれば、いつでもメールな どが受け取れます。受取人がいないメールは、その一 - E 流の 計算機に保管されています。それがほかの組織の計算機の 場合には、ちょっと気を遣いますね。だから、せめて各組 織に 1 台は年中無休の計算機があるといいかもしれませ UNIX MAGAZINE 1991.6
ワークステーションのおと一 $ bash /tmp/xxx "first a て second arg first arg $ sh /tmp/xxx "first arg' second arg second arg ところが bash を使い始めたころ、私は type コマン ドの存在を知らなかったので、 function で which を 作ってしまいました。 ⅶ土 c 五 ( ) { 1 ] ; then echO "Usage : W 土 C command—name' first arg second arg となってしまいます。 " $ を使し、ます。 $ c at yyy for i 土Ⅱ " $ " do echO $ 土 done $ bash /tmp/yyy first arg second arg これを避けるには、明示的に else aliases='alias $ 1 if [ "$aliases" ! = then echO $aliases return found= f0 て d 土て in ${path- . } do , path=$PATH if [ -x $ d 近 / $ 1 -a ! then e 曲 0 $ d 近 / $ 1 found=true done if [ "$found" ! = "true then echo Ⅱ 0 $ 1 土Ⅱ $path IFS=' -d $dir/$l ] "first arg second arg シェル変数未定義のシェル変数をある条件で参照す るとコアダンフ。してしまいます。ここでは first には 値が言聢されていますが、 second には設定されていま せん。 $ first=AAAA $ x=${first}/${second} free : CaIIed with already freed block argume nt TeII env@astec ・ co ・ JP to fix this someday. . Segmentation fault Mai1ing a bug report . 参考 C シェルでは、 which を使って、コマンドがファ イルシステムのどこにあるかを捜すことができました。 bash では、 type という組込みコマンドを使えば同じ ことができます。 UNIX MAGAZINE 1991.6 この function は alias を捜す部分以外は bash に依 存していません。ですから、 function がある B シェル でも実行できるはずで 4 。ところが、ところが、うま く動きません。 path=$PATH , IFS= , の部分を IFS=$IFS : path=$PATH としないとだめなのてす。 微妙なところで B シェルと違うようですオ ( さかした・しゅう ASTEC) 4 test で—x を使っているところがあるので、このままでよ SunOS でしカ行できません。 103
ワークステーションのおと一⑩ 移行の注意 同様なことを . bas c でしようとして、 と書くことがでぎます。 if ($?prompt 0 ) exit 断をするときには、 exit . cshrc のなかで対話型のシェルかどうかを判 実行すると止まらなくなります。 C シェルだと、 . cshrc のなかで which コマンドを の繰り返しになってしまうのてす。 5. ふたたび初期化のために . bashrc を読み込む する 4. そのスクリフ。トを bash が実行しようとして、 fork いシェルスクリフ。ト」をふたたび実行しようとする 3.. bashrc のなかの「実行するシェルを明示していな 込む 2. fork した bash が初期化のために . bashrc を読み 1. bash が fork する が fork して実行しようとするからてす。つまり、 これよ、実行するシェルが明示されていないと bash bash カ際限なく fork してしまい、終らなくなります。 クリフ。トを . bashrc のなかから実行しようとすると、 のように、実行するシェルを明示していないシェルス # ! /bin/sh シェルスクリプト先頭行に if [ "$PSI'I exit ー ] ; then とすると、以降のシェルスクリフ。トが実行されません。 これでは、 rsh コマンドを使ってリモートでコマンド を実行する場合に困ります。 1. rsh を起動する 2. リモートのホストのログインシェルも bash の場合、 bash が起動され . bashrc カ陝行される 3. 対話型のシェルではなし、ので exit が実行される 4. C シェルだと . cshrc の実行を終了して、 rsh で指 定されたコマンドを実行する UNIX MAGAZINE 1991.6 5. ところが、 bash では rsh から起動された bash が終 了してしまい、 rsh で指定されたコマンドは実行され ない となってしまうのてす。 て一茆から . bashrc では ー ] ; then 対話型シェルのときの処理 と書いておきます。 . twmrc など X のウインドウ・マネージャーでは、 ーからシェルコマンドが実行できます。多くは メニュ ログインシェルが実行するようになっているので、シェ ルの種類に依存した記述、たとえばリダイレクトなどは 書き換えなけれよいけません。 演算機能意外なことに、 C シェルのを使った演算 機能に相当するものがありません。 alias と function bash では alias で引数を渡す一 とができません。そのため、引数が必要なものは func- tion を使う必要があります。 C シェルで、 alias nless 'nkf \!*lless としていたものは、 nless ( ) { nkf $ 1 ー less } となります。 同じように、 alias cd ' set old=$cwd; chdir \ ! * ' alias back ' set back=$old; set old=$cwd, cd $back; unset back; pwd' も書き換えると、 cd ( ) { old=$cwd; chdir $ * } back ( ) { back=$old; old=$cvd, chdir $back ; unset back ; pwd } となります。ところが、 bash には chdir がないので、 chdir を cd に置き換えると、自分自身を呼び出して無 限ルーフ。に陥ってしまいます。 解決策を挙げておきましよう。まず、 builtin コマン builtin cd ドを使って、 101
図ー シングルユーサー・モード 立ち上がり手川頁 スイッチ ON セルフテスト Boot Rom ハードウェア情報の表示 メモリチェック カーネルの読込み /sbin/init の起動 ()h の起動 ) /etc/rc. b00t の呼出し /etc/fsck の実行 失敗 成功 etc て . sin 厄の呼出し /etc/rc の呼出し etc/rc. local の呼出し # ! /bin/sh ー ◇ rc の例 ・リストー rc ファイル @(#)rc 1 .44 89 / 08 / 29 SMI ; from UCB 4.3 マルチューサー・モード /etc/getty の起 # 4.1a7 change : 盟 1e rc sh gets the console. A11 commands are by # default protected from tty signals (). e. are not interruptable) . # lnterrupts can be enabled by proceeding any command line with "intr't # CO れ S01e redirection is no longer needed. # Make sure PATH is exported or intr won 't find what it needs. HO ト = / ; export HO 寵 PAN=/bin: /usr/bin:/usr/etc; export PAffI # See if things 100k like they are still mounted read—only. # If so , perfom a11 the remounting 田 ld set up work now. touch / if [ $ ? —ne 0 ] ; then ech0 "Remounting file systems't sh /etc/rc. single fi 32 UNIX MAGAZINE 1991.6
N 正 = $ 4 " . " DEFAULT_DOMAIN printf ("%s c %s()'t , NAME, DOMAIN) # host infomation record rest $ 4 , $ 5 ) # so れ # 1 sort ー # awk # 2 BEGIN{ 80 else if ( $ 3 else # put comments for (i = rest ; if ( CO ト日『 ! = COMMENTS = " " "hinfo"){ printf ("%s h %s % 号 0 " , DOMAIN, rest = 6 next 1 Ⅱ one place as 田 1 additional record 土く = NF; i + + ) COPTENTS = C(]OENTS " " $i printf ("%s x %s0" , HOSTNAME, CO S ) sort the intemediate records according to fully—qualified hostname 田 ld then by record type generate the hosts file fonnat line ( with a m1 れ or modification) from the intemediate file 0UTPtn = " " naddr = 0 ; HOSTNAME = CO ト日げ S = NICKS = 0 OU Ⅳ [ = OÜⅣ ( " " NICKNAMES[i] for( i # add the shortened nicknames to the record # output last host 1ine "a") { # first "a't record else if ( $ 2 ADDRESS [ + + Ⅱ ad ] = $ 3 HOSI ) # subsequent record if ( $ 2 # if an address record, print output Iine 田 id staart new 0 e BADNI(XNAPE = BADNICKNAhE " " "loopback" BADNICKNAME = BADNICKNAPE " " 'tloghosttt BADNICKNAPE = "localhost " # nicknames with are not allowed ADDRESS [ + + naddr] = $ 3 naddr = 0 P [ = $ 1 HOSTNAME = $ 1 NICKS = 0 printf ("%s. %s0, ADDRESS [i] , 1 ; i く = naddr; i + + ) for (i if ( 既 P ( " " # its used in the next stage of the script inserted after the IP address # note the # print complete output record # print actual output 1ine CO 旧 S = ” " 0 [ P ( 灯 = OI 灯 P [ " # " CO ト↓ TS if(COMMENTS " " # put on comments 0 町 P 町 ) # start new output Iine , using data from authoritative record # add new authoritative name to its niclmarne 1ist Ⅱ = split()l ,nickarray, UNIX MAGAZINE 1991.6
if (ofpath = NULL) { ofd = 1 ; } else { logblksiz = 512 * 2 ; logblksiz = 512 * 4 ; / * stdout * / if ( 矼 . st. st-dev ofsdev) { / * 同じファイルシステムかどうかの検査 * / ofsdev = st. st_dev ; fstat(ofd, &st) ; / * 出力ファイルのシステムデノヾイス id の取得 * / exit (EXIT—FAILURE) ; perror("opening output file") ; if (ofd ー ofd = open(ofpath, O-WRONLY ー O—CREAT ー 0 ・ IRUNC, / * 出力ファイルの作成 * / 0 ) ; fputs("outfile must on different file system than\ deleted file. \n" , stderr) ; unlink (ofpath) ; exit(EXIT_FAII. URE) ; / * 所有者、グループおよび許可を元のファイルと同じに設定する * / sprintf(fspath, 't%s/%s" , FSDEVDIR, de 0 Ⅱ ( 矼 . st. st-dev)) ; / * ファイルシステムのデハ・イスのオープン * / chmod(ofpath, 矼 . st. st—mode) ; chown(ofpath, 矼 . st. st—uid, 矼 . st. st-gid) ; switch (fs. s-type) { } else { logblksiz = 512 ; if (fs. s-magic ! = FsMAGIC) { / * 論理プロックサイズの決定 * / exit (EXIT—FAILURE) ; perror('treadlng super block't) ; if ( 皿く sizeof(fs) ) { 矼 = read(fsfd, &fs , (unsigned)sizeof(fs) ) ; lseek(fsfd, (10ng)PHYSBLKSIZ, SEEK—SED ; / * スーノく一プロックの読取り * / exit(EXIT_FAILURE) ; perror("opening disk device") ; if (fsfd ー fsfd = open(fspath, O—RDONLY) ; case Fs1b: logblksiz break; case Fs2b : break ; case Fs4b: break; default: = 512 ; fputs("lnvalid file system type ・ \n" exit (EXIT—FAII. URE) ; / * プロックノヾッフアの割当 * / for (i = 0 ; i く nelems(blkbufv) ; + + i ) { blkbufv[i] = (char *)malloc((size-t)logblksiz) ; / * ファイルデータの復元 * / tnw = 0 ; / * 直接プロックアドレス * / for (i = 0 ; i く BATDIRC; + + i ) { if (tnv > = . st. st—size) { break ; getbataddr(blkaddr, 矼 . bat' i) ; stderr) ; nw = recover(fsfd, logblksiz' blkaddr' 0 , 矼 . st. st—size if ( れ perror("error recovering file data") ; exit (EXIT—FAII. URE) ; tnw 十 = nw; UNIX MAGAZINE 1991.6 tnw, ofd) ; UNIX ファイルの復元■ 117
ンタ # if a cname else if ( $ 2 e1se if( $ 2 # additional commentary e1se if( $ 2 nID { printf ("%s. %s0" , ADDRESS[i] , 0 町 P ) # if nickname is lowd , add it tO the 1ist ; イ # but those are silly names , anyhow # disallowed れ e (like 10g , mail, etc. ) # fail for any name which is a substring 0f a # this is 田一 xmprecise but fast check; it 3i11 if( ! index(BADNICKNAME, nickarray[l] ) ) { 0 ( 以 ? ( = ourptrr " " $ 3 # append i HOSTNAME) { record, append i t0 output line NICKNAMES[ + + NICKS] = nickarray [ 1 ] ネ ッ トへの接続■ # add shortened alias t0 nickname array if not already there; # we ould 1ike t0 use index() for this function, since it is # much faster than this 100P , but it would fail for cases like Ⅱ = sp1it($3,nickarray,". ") for(i = 1 ; ! (i > NICKS) ; i + + ) { if (NICKNAMFS[i] if (i > NICKS) { nickarray[l] ) break # if nickname is allowed, add it t0 the 1ist if( ! index(BADNICKNAME, nickarray[l] ) ) { NICKNAMES[ + + NICKS] # if a hinfO record, save the CO ents for output = nickarray[l] $i ー HOSTNAME) { ー HOSTNAME){ for (i = 3 ; for (i = 3 ; "h" 誠 $ 1 # output 1ast hOSt line sed ' s た 10. / 255. / ' は # a small hack tO put ARPANET hosts entries last in the output print(" ' "$startofdata't ' " ) # append delimiter which is a later removed for (i 1 ; i く = naddr; i + + ) # its used in the next stage Of the script # note the " . inserted after the IP address # print complete output record # print actual output 1 ine COPMENTS Ot.rrPtJT = OU Ⅳ ( " # " COFTENTS if(C(]•ffENTS ! = # put on comments OIJI?I-rr = 0 び rp ー " " NICKN. 鮎僞[i] for( i # add the shortened nicknames tO the record = CO 側 S CO ト旧「 rs " # sort # 2 ー SO れ the file int0 IP address order for fina1 output fomatting sort ー -t. + 0 ー 1 + 1 ー 2 + 2 ー 3 + 3 ー 4 憘 # sed # 1 ー strxp out the extra ". " after the IP address and replace with tab UNIX MAGAZINE 1991.6 81