23.4 ­«·s½sĶ ¡§world¡¨

¦b§ó·s FreeBSD ªº source tree ¨ì³Ì·s¤§«á(µL½×¬O FreeBSD-STABLE¡B FreeBSD-CURRENT µ¥µ¥)¡A±µ¤U¨Ó´N¥i¥H¥Î³o¨Ç source tree ¨Ó­«·s½s͍t²Î ¡C

°µ¦n³Æ¥÷: ¦b§@¥ô¦ó¤j°Ê§@ ¤§«e ­n°O±o¥ý§â¨t²Î§@³Æ¥÷ªº­«­n©ÊµL¶·±j½Õ¡C ¾¨ºÞ­«·s½sĶ world ¬O (¥u­n¦³·Ó¤å¥ó«ü¥Ü¥h§@ªº¸Ü)¤@¥ó«Ü²³æªº¨Æ±¡¡A¦ý¥X¿ù¤]¬O¦b©ÒÃø§Kªº¡C ¥t¥~¡A§O¤H¦b source tree ¤£·V·d²Vªº¿ù»~¡A¤]¥i¯à·|³y¦¨¨t²ÎµLªk¶}¾÷ ¡C

½Ð½T»{¦Û¤v¤w§@§´¬ÛÃö³Æ¥÷¡A¨Ã¥B¤âÃ䦳 fixit ºÏ¤ù©Î¶}¾÷¥úºÐ¡C ±z¥i¯à¥Ã»·¤]¥Î¤£¨ì³o¨ÇªF¦è¡A ¦ý¦w¥þ²Ä¤@Á`¤ñ¨Æ«á»¡©êºp¨Ó±o¦n§a¡I

­q¾\¬ÛÃöªº Mailing List: FreeBSD-STABLE ¥H¤Î FreeBSD-CURRENT ¤À¤ä¡A¥»½è¤W´N¬OÄÝ©ó ¶}µo¶¥¬q¡C ¬° FreeBSD §@°^Ämªº¤]³£¬O¤H¡A°¸º¸¤]·|¥Ç¿ù»~¡C

¦³®É­Ô³o¨Ç¿ù»~¨ÃµL¤jê¡A¥u¬O·|Åý¨t²Î²£¥Í·sªº¿ù»~ĵ§i¦Ó¤w¡C ¦³®É«h¬O¨aÃø¡A¥i¯à·|¾É­P¤£¯à¶}¾÷©ÎÀɮרt²Îªº·´·l(©Î§óÁV)¡C

­Y¹J¨ìÃþ¦ü°ÝÃD¡A¶K«Ê¼ÐÃD¬° ¡§heads up(ª`·N)¡¨ ¶}ÀYªº«H¨ì¬ÛÃöªº mailing list¡A¨ÃÁ¿²M·¡°ÝÃDÂI¥H¤Î·|¼vÅT­þ¨Ç¨t²Î¡C ¦b°ÝÃDÀò¸Ñ¨M«á¡A¦A¶K¼ÐÃD¬° ¡§all clear(¤w¸Ñ¨M)¡¨ ¶}ÀYªºÁn©ú«H¡C

­Y¥Îªº¬O FreeBSD-STABLE ©Î FreeBSD-CURRENT¡A«o¤S¤£¾\Ū FreeBSD-STABLE ¶l»¼½×¾Â ©Î FreeBSD-CURRENT ¶l»¼½×¾Â ªº°Q½×¡A¨º»ò·|¬O¦Û§ä³Â·Ð¦Ó¤w¡C

¤£­n¥Î make world: ¤@°ï¦­´ÁªºÂ¤å¥ó³£·|«ØÄ³»¡¨Ï¥Î make world¡C ³o¼Ë°µ·|¸õ¹L¤@¨Ç­«­n¨BÆJ¡A«ØÄ³¥u¦³¦b§Aª¾¹D¦Û¤v¦b§@¤°»ò¡A¦A³o»ò°µ¡C ¦bµ´¤j¦h¼Æªº±¡ªp¤U¡A½Ð¤£­n¶Ã¥Î make world¡A ¦Ó¸Ó§ï¥Î¤U­±¤¶²Ðªº¤è¦¡¡C

23.4.1 §ó·s¨t²Îªº¼Ð·Ç¤è¦¡

­n¤É¯Å¨t²Î«e¡A¤@©w­n¥ý¬d¾\ /usr/src/UPDATING ¤å¥ó¡A¥HÁA¸Ñ buildworld ¤§«e»Ý­n§@­þ¨Ç¨Æ±¡©Îª`·N¨Æ¶µ¡A µM«á¤~¥Î¤U¦C¨BÆJ¡G

# make buildworld
# make buildkernel
# make installkernel
# reboot

Note: ¦b¤Ö¼Æª¬ªp¡A¥i¯à»Ý­n¥ý¦b buildworld ¨BÆJ¤§«e¥ý§@ mergemaster -p ¤~¯à§¹¦¨¡C ¦Ü©ó¦ó®É»Ý­n©Î¤£»Ý­n¡A½Ð°Ñ¾\ UPDATING ¤ºªº»¡©ú¡C ¤@¯ë¨Ó»¡¡A¥u­n¤£¬O¶i¦æ¸óª©¸¹(major)ªº FreeBSD ª©¥»¤É¯Å¡A ´N¥i²¤¹L³o¨BÆJ¡C

§¹¦¨ installkernel ¤§«á¡A»Ý­n­«¶}¾÷¨Ã¤Á¨ì single user ¼Ò¦¡(Á|¨Ò¡G¤]¥i¥H¦b loader ´£¥Ü²Å¸¹«á­±¥[¤W boot -s)¡C ±µ¤U¨Ó°õ¦æ¡G

# mergemaster -p
# make installworld
# mergemaster
# reboot

Read Further Explanations: ¤W­z¨BÆJ¥u¬O¨ó§U±z¤É¯ÅªºÂ²³æ»¡©ú¦Ó¤w¡A­Y­n²M·¡ÁA¸Ñ¨C¤@¨BÆJ¡A ¤×¨ä¬O­Y±ý¦Û¦æ¥´³y kernel ³]©w¡A´N§ó¸Ó¾\Ū¤U­±ªº¤º®e¡C

23.4.2 ¾\Ū /usr/src/UPDATING

¦b§@¥ô¦ó¨Æ±¡¤§«e¡A½Ð°È¥²¥ý¾\Ū /usr/src/UPDATING (©Î¦b source code ¤ºÃþ¦üªº¤å¥ó) ¡C ³o¥÷¤å¥ó·|¼g¨ì¥i¯à¾D¹Jªº°ÝÃD¡A©Î«ü©w¨º¨Ç·|°õ¦æªº«ü¥O¶¶§Ç¬°¦ó¡C ¦pªG§A¾÷¾¹²{¦bªº UPDATING ¤å¥ó»P³oÃ䪺´y­z¦³½Ä¬ð¡B¥Ù¬Þ¤§³B¡A¨º»ò½Ð¥H¾÷¾¹¤Wªº UPDATING ¬°·Ç¡C

Important: µM¦Ó¡A¦p¦P¥ý«e©Ò­z¡A³æ³æ¥u¾a¾\Ū UPDATING ¨Ã¤£¯à§¹¥þ¨ú¥N mailing list¡C ³o¨âªÌ³£¬O¤¬¸Éªº¡A¦Ó¤£¬Û±Æ¥¸¡C

23.4.3 Àˬd /etc/make.conf

Àˬd /usr/share/examples/etc/make.conf ¥H¤Î /etc/make.conf¡C ²Ä¤@¥÷¤å¥ó¤D¬O¤@¨Ç¨t²Î¹w³]­È - ¤£¹L¡A¤j³¡¤À³£³Qµù¸Ñ°_¨Ó¡C ¬°¤F¦b­«·s½sͮɝà°÷¨Ï¥Î³o¨Ç¡A ½Ð§â³o¨Ç³]©w¥[¨ì /etc/make.conf¡C ½Ðª`·N¦b /etc/make.conf ªº¥ô¦ó³]©w¤]·|¼vÅT¨ì¨C¦¸¨Ï¥Î make ªºµ²ªG¡A ¦]¦¹³]©w¤@¨Ç¾A¦X¦Û¤v¨t²Îªº¿ï¶µ·|¬O¤£¿ùªº§@ªk¡C

¤@¯ë¨Ï¥ÎªÌ³q±`·|±q /usr/share/examples/etc/make.conf ½Æ»s CFLAGS ¥H¤Î NO_PROFILE ¤§Ãþªº³]©w¨ì /etc/make.conf¡A¨Ã¸Ñ°£¬ÛÃöµù¸Ñ¦L°O ¡C

¦¹¥~¡A¤]¥i¥H¸Õ¸Õ¬Ý¨ä¥L³]©w (COPTFLAGS¡B NOPORTDOCS µ¥µ¥)¡A¬O§_²Å¦X¦Û¤v©Ò»Ý¡C

23.4.4 §ó·s /etc ¤ºªº³]©wÀÉ

¦b /etc ¥Ø¿ý·|¦³¨t²Îªº¬ÛÃö³]©wÀÉ¡A ¥H¤Î¶}¾÷®Éªº¦U¶µªA°È±Ò°Ê script¡C ¦³¨Ç script ÀH FreeBSD ª©¥»ªº¤£¦P¦Ó¦³¨Ç®t²§¡C

¨ä¤¤¦³¨Ç³]©wÀÉ·|¦b¨C¤é¹B§@ªº¨t²Î¸Ì¤]·|¥Î¨ì¡C ¤×¨ä¬O /etc/group¡C

¦³®É­Ô¦b make installworld ¦w¸Ë¹Lµ{¤¤¡A ·|»Ý­n¥ý«Ø¥ß¬Y¨Ç¯S©w±b¸¹©Î¸s²Õ¡C ¦b¶i¦æ¤É¯Å¤§«e¡A¥¦­Ì¥i¯à¨Ã¤£¦s¦b¡A ¦]¦¹¤É¯Å®É´N·|³y¦¨°ÝÃD¡C ¦³®É­Ô make buildworld ·|¥ýÀˬd³o¨Ç©Ò»Ýªº±b¸¹©Î¸s²Õ¬O§_¤w¦³¦s¦b¡C

Á|­Ó³o¼Ëªº¨Ò¤l¡A¹³¬O¬Y¦¸¤É¯Å¤§«á¥²¶··s¼W smmsp ±b¸¹¡C ­Y¨Ï¥ÎªÌ©|¥¼·s¼W¸Ó±b¸¹´N­n§¹¦¨¤É¯Å¾Þ§@ªº¸Ü¡A ·|¦b mtree(8) ¹Á¸Õ«Ø¥ß /var/spool/clientmqueue ®Éµo¥Í¥¢±Ñ¡C

¸Ñªk¬O¦b buildworld ¶¥¬q¤§«e¡A¥ý°õ¦æ mergemaster(8) ¨Ã·f°t -p ¿ï¶µ¡C ¥¦·|¤ñ¹ï¨º¨Ç°õ¦æ buildworld ©Î installworld ©Ò»Ý¤§ÃöÁä³]©wÀÉ¡C ­Y§A©Ò¥Îªº¬O¦­´Á¤´¥¼¤ä´© -p ªº mergemaster ª©¥»¡A¨º»òª½±µ¨Ï¥Î source tree ¤ºªº·sª©§Y¥i¡G

# cd /usr/src/usr.sbin/mergemaster
# ./mergemaster.sh -p

Tip: ­Y±z¬O°¾°õ¨g(paranoid)¡A ¥i¥H¹³¤U­±³o¼Ë¥h¸ÕµÛÀˬd¨t²Î¤W¦³­þ¨ÇÀÉ®×ÄÝ©ó¤w§ï¦W©Î³Q§R°£ªº¸s²Õ ¡G

# find / -group GID -print

³o·|Åã¥Ü©Ò¦³²Å¦X­n§äªº GID ¸s²Õ (¥i¥H¬O¸s²Õ¦WºÙ¡A©ÎªÌ¬O¸s²Õªº¼Æ¦r¥N¸¹)ªº©Ò¦³ÀɮסC

23.4.5 ¤Á´«¨ì Single User ¼Ò¦¡

±z¥i¯à·|·Q¦b single user ¼Ò¦¡¤U½s͍t²Î¡C °£¤F¥i¥H©úÅã§ó§Ö§¹¦¨¤§¥~¡A¦w¸Ë¹Lµ{¤¤±N·|²o¯A³\¦h­«­nªº¨t²ÎÀɮסA ¥]¬A©Ò¦³¨t²Î binaries¡Blibraries¡Binclude ÀÉ®×µ¥¡C ­Y¦b¹B§@¤¤ªº¨t²Î(¤×¨ä¦³³\¦h¨Ï¥ÎªÌ¦b¥Îªº®É­Ô)¤º§ó§ï³o¨ÇÀɮסA ¨ºÂ²ª½¬O¦Û§ä³Â·Ðªº§@ªk¡C

¥t¤@ºØ¼Ò¦¡¬O¥ý¦b multi-user ¼Ò¦¡¤U½sͦn¨t²Î¡AµM«á¦A¤Á¨ì single user ¼Ò¦¡¥h¦w¸Ë¡C ­Y±z¤ñ¸û³ßÅw³oºØ¤è¦¡¡A¥u»Ý¦b build(½s͹Lµ{) §¹¦¨¤§«á¡A ¦A¥h°õ¦æ¤U­±ªº¨BÆJ§Y¥i¡C ¤@ª½¨ì¥i¤Á´« single user ¼Ò¦¡®É¡A¦A¥h°õ¦æ installkernel ©Î installworld §Y¥i¡C

¤Á´«¬° root ¨­¥÷¥´¡G

# shutdown now

³o¼Ë´N·|±q­ì¥»ªº multi-user ¼Ò¦¡¤Á´«¨ì single user ¼Ò¦¡¡C

°£¦¹¤§¥~¤]¥i¥H­«¶}¾÷¡A±µµÛ¦b¶}¾÷¿ï³æ³B¿ï¾Ü ¡§single user¡¨ ¿ï¶µ¡C ¦p¦¹¤@¨Ó´N·|¶i¤J single user ¼Ò¦¡¡A µM«á¦b shell ´£¥Ü²Å¸¹³B¿é¤J¡G

# fsck -p
# mount -u /
# mount -a -t ufs
# swapon -a

³o¼Ë·|¥ýÀˬdÀɮרt²Î¡A¨Ã­«·s±N / §ï¥H¥iŪ¼gªº¼Ò¦¡±¾¸ü¡A¥H¤Î /etc/fstab ¤º©Ò³]©wªº¨ä¥L UFS Àɮרt²Î¡A³Ì«á±Ò¥Î swap ºÏ°Ï¡C

Note: ­Y CMOS ®ÉÄÁ¬O³]¬°·í¦a®É¶¡¡A¦Ó«D GMT ®É°Ï(­Y date(1) «ü¥O¨SÅã¥Ü¥¿½Tªº®É¶¡¡B®É°Ï)¡A¨º¥i¯à»Ý­n¦A¿é¤J¤U¦C«ü¥O¡G

# adjkerntz -i

³o¨BÆJ¥i¥H½T»{±zªº·í¦a®É°Ï³]©w¬O§_¥¿½T ¡X¡X §_«h¤é«á·|³y¦¨¤@¨Ç°ÝÃD¡C

23.4.6 ²¾°£ /usr/obj

¦b­«·s½s͍t²Îªº¹Lµ{¤¤¡A½s͵²ªG·|©ñ¨ì(¹w³]±¡ªp) /usr/obj ¤º¡C ³o¸Ì­±ªº¥Ø¿ý·|¹ïÀ³¨ì /usr/src ªº¥Ø¿ýµ²ºc¡C

¬å±¼³o¥Ø¿ý¡A¥i¥HÅý¥H«áªº make buildworld ¹Lµ{§ó§Ö¤@¨Ç¡A¦Ó¥B¥iÁ×§K¥H«e½sĶªºªF¦è¸ò²{¦bªº²V²c¦b¤@°_ªº¬Û¨Ì¿ù¶Ã ¡C

¦Ó¦³¨Ç /usr/obj ¤ºªºÀÉ®×¥i¯à·|³]©w¤£¥i§ó°Êªº flag(²Ó¸`½Ð°Ñ¾\ chflags(1))¡A¦Ó¥²¶·¥ý®³±¼³o¨Ç flag ³]©w¤~¦æ ¡C

# cd /usr/obj
# chflags -R noschg *
# rm -rf *

23.4.7 ­«·s½sĶ Base System

23.4.7.1 «O¯d½sĶªº¬ö¿ý

«ØÄ³¾i¦¨¦n²ßºD¡A§â°õ¦æ make(1) ®É²£¥Íªº¬ö¿ý¦s°_¨Ó¡C ³o¼Ë­Y¦³­þÃä¥X¿ù¡A´N·|¦³¿ù»~°T®§ªº¬ö¿ý¡C ÁöµM³æ³æ³o¼Ë¡A §A¥i¯à¤£ª¾¹D¦p¦ó¤ÀªR¬O­þÃä¥X¤F§Ã¡A¦ý­Y§â§A°ÝÃD°O¿ý¶K¨ì FreeBSD ¬ÛÃöªº mailing list ´N¥i¥H¦³¤H¥i¥HÀ°¦£¬Ý¬O«ç»ò¤@¦^¨Æ±¡¡C

³Ì²³æªº¤è¬O´N¬O¥Î script(1) «ü¥O¡A¨Ã¥[¤W°Ñ¼Æ (§A·Q¦s©ñ°O¿ýªºÀɮצì¸m¡BÀɦW)§Y¥i¡C ³o¨BÆJÀ³¸Ó¦b­«·s½s͍t²Î®É´N­n§@¡AµM«á¦b§¹¦¨½sĶ«á¿é¤J exit §Y¥iÂ÷¶}¡C

# script /var/tmp/mw.out
Script started, output file is /var/tmp/mw.out	 
# make TARGET
... compile, compile, compile ...	  
# exit
Script done, ...

¹ï¤F¡AÁÙ¦³¤@ÂI¾¨¶q§O§âÀɮצs¨ì /tmp ¥Ø¿ý¤º¡C ¦]¬°­«¶}¾÷¤§«á¡A ³o¥Ø¿ý¤ºªºªF¦è³£·|³Q²MªÅ¡C ¤ñ¸û§´µ½ªº¦a¤è¬O /var/tmp (¦p¤W¨Ò©Ò¥Ü) ©ÎªÌ¬O root ªº®a¥Ø¿ý¡C

23.4.7.2 ½sĶ Base System

­º¥ý½Ð¥ý¤Á´«¨ì /usr/src ¥Ø¿ý¡G

# cd /usr/src

(·íµM¡A°£«D§A§â source code ©ñ¨ì¨ä¥L¦a¤è¡A­Y¯u¬O³o¼Ë¡A ´N¤Á´«¨ì¨º­Ó¥Ø¿ý§Y¥i)¡C

¨Ï¥Î make(1) «ü¥O¨Ó­«·s½sĶ world¡C ³o«ü¥O·|±q Makefile ÀÉ(³oÀÉ·|¼g FreeBSD ªºµ{¦¡¸Ó¦p¦ó­«·s½sĶ¡B¥H­þ¨Ç¶¶§Ç¨Ó½s͵¥µ¥)¥hŪ¨ú¬ÛÃö«ü¥O¡C

¤@¯ë¤U«ü¥Oªº®æ¦¡¦p¤U¡G

# make -x -DVARIABLE target

¦b³o­Ó¨Ò¤l¡A-x ¬O§A·Q¶Çµ¹ make(1) ªº¿ï¶µ¡A²Ó¸`»¡©ú½Ð°Ñ¾\ make(1) »¡©ú¡A ¸Ì­±¦³¬ÛÃö½d¨Ò»¡©ú¡C

-DVARIABLE «h¬O§âÅܼƳ]©w¶Çµ¹ Makefile¡C ³o¨ÇÅܼƷ|±±¨î Makefile ªº¦æ¬°¡C ³o¨Ç³]©w»P /etc/make.conf ªºÅܼƳ]©w¬O¤@¼Ë¡A ¥u¬O¥t¤@ºØ³]©w¤è¦¡¦Ó¤w¡C

# make -DNO_PROFILE target

¤W­±ªº¨Ò¤l«h¬O¥t¤@ºØ³]©w¤è¦¡¡A¤]´N¬O­þ¨Ç¤£­n¡C ³o­Ó¨Ò¤l¤¤ªº·N«ä¬O¤£¥h½sĶ profiled libraries¡A®ÄªG´N¦p¦P³]©w¦b /etc/make.conf ªº

NO_PROFILE=    true 	#    Avoid compiling profiled libraries

target «h¬O§i¶D make(1) ¸Ó¥h°µ­þ¨Ç¡C ¨C­Ó Makefile ³£·|©w¸q¤£¦Pªº ¡§targets¡¨¡AµM«á¨Ì±z©Òµ¹ªº target ´N·|¨M©w·|°µ­þ¨Ç°Ê§@ ¡C

Some targets are listed in the Makefile, but are not meant for you to run. Instead, they are used by the build process to break out the steps necessary to rebuild the system into a number of sub-steps.

Most of the time you will not need to pass any parameters to make(1), and so your command like will look like this:

# make target

Where target will be one of many build options. The first target should always be buildworld.

As the names imply, buildworld builds a complete new tree under /usr/obj, and installworld, another target, installs this tree on the current machine.

Having separate options is very useful for two reasons. First, it allows you to do the build safe in the knowledge that no components of your running system will be affected. The build is ¡§self hosted¡¨. Because of this, you can safely run buildworld on a machine running in multi-user mode with no fear of ill-effects. It is still recommended that you run the installworld part in single user mode, though.

Secondly, it allows you to use NFS mounts to upgrade multiple machines on your network. If you have three machines, A, B and C that you want to upgrade, run make buildworld and make installworld on A. B and C should then NFS mount /usr/src and /usr/obj from A, and you can then run make installworld to install the results of the build on B and C.

Although the world target still exists, you are strongly encouraged not to use it.

Run

# make buildworld

It is possible to specify a -j option to make which will cause it to spawn several simultaneous processes. This is most useful on multi-CPU machines. However, since much of the compiling process is IO bound rather than CPU bound it is also useful on single CPU machines.

On a typical single-CPU machine you would run:

# make -j4 buildworld

make(1) will then have up to 4 processes running at any one time. Empirical evidence posted to the mailing lists shows this generally gives the best performance benefit.

If you have a multi-CPU machine and you are using an SMP configured kernel try values between 6 and 10 and see how they speed things up.

23.4.7.3 Timings

Many factors influence the build time, but fairly recent machines may only take a one or two hours to build the FreeBSD-STABLE tree, with no tricks or shortcuts used during the process. A FreeBSD-CURRENT tree will take somewhat longer.

23.4.8 Compile and Install a New Kernel

To take full advantage of your new system you should recompile the kernel. This is practically a necessity, as certain memory structures may have changed, and programs like ps(1) and top(1) will fail to work until the kernel and source code versions are the same.

The simplest, safest way to do this is to build and install a kernel based on GENERIC. While GENERIC may not have all the necessary devices for your system, it should contain everything necessary to boot your system back to single user mode. This is a good test that the new system works properly. After booting from GENERIC and verifying that your system works you can then build a new kernel based on your normal kernel configuration file.

On FreeBSD it is important to build world before building a new kernel.

Note: If you want to build a custom kernel, and already have a configuration file, just use KERNCONF=MYKERNEL like this:

# cd /usr/src
# make buildkernel KERNCONF=MYKERNEL
# make installkernel KERNCONF=MYKERNEL

Note that if you have raised kern.securelevel above 1 and you have set either the noschg or similar flags to your kernel binary, you might find it necessary to drop into single user mode to use installkernel. Otherwise you should be able to run both these commands from multi user mode without problems. See init(8) for details about kern.securelevel and chflags(1) for details about the various file flags.

23.4.9 Reboot into Single User Mode

You should reboot into single user mode to test the new kernel works. Do this by following the instructions in Section 23.4.5.

23.4.10 Install the New System Binaries

If you were building a version of FreeBSD recent enough to have used make buildworld then you should now use installworld to install the new system binaries.

Run

# cd /usr/src
# make installworld

Note: If you specified variables on the make buildworld command line, you must specify the same variables in the make installworld command line. This does not necessarily hold true for other options; for example, -j must never be used with installworld.

For example, if you ran:

# make -DNO_PROFILE buildworld

you must install the results with:

# make -DNO_PROFILE installworld

otherwise it would try to install profiled libraries that had not been built during the make buildworld phase.

23.4.11 Update Files Not Updated by make installworld

Remaking the world will not update certain directories (in particular, /etc, /var and /usr) with new or changed configuration files.

The simplest way to update these files is to use mergemaster(8), though it is possible to do it manually if you would prefer to do that. Regardless of which way you choose, be sure to make a backup of /etc in case anything goes wrong.

23.4.11.1 mergemaster

Contributed by Tom Rhodes.

The mergemaster(8) utility is a Bourne script that will aid you in determining the differences between your configuration files in /etc, and the configuration files in the source tree /usr/src/etc. This is the recommended solution for keeping the system configuration files up to date with those located in the source tree.

To begin simply type mergemaster at your prompt, and watch it start going. mergemaster will then build a temporary root environment, from / down, and populate it with various system configuration files. Those files are then compared to the ones currently installed in your system. At this point, files that differ will be shown in diff(1) format, with the + sign representing added or modified lines, and - representing lines that will be either removed completely, or replaced with a new line. See the diff(1) manual page for more information about the diff(1) syntax and how file differences are shown.

mergemaster(8) will then show you each file that displays variances, and at this point you will have the option of either deleting the new file (referred to as the temporary file), installing the temporary file in its unmodified state, merging the temporary file with the currently installed file, or viewing the diff(1) results again.

Choosing to delete the temporary file will tell mergemaster(8) that we wish to keep our current file unchanged, and to delete the new version. This option is not recommended, unless you see no reason to change the current file. You can get help at any time by typing ? at the mergemaster(8) prompt. If the user chooses to skip a file, it will be presented again after all other files have been dealt with.

Choosing to install the unmodified temporary file will replace the current file with the new one. For most unmodified files, this is the best option.

Choosing to merge the file will present you with a text editor, and the contents of both files. You can now merge them by reviewing both files side by side on the screen, and choosing parts from both to create a finished product. When the files are compared side by side, the l key will select the left contents and the r key will select contents from your right. The final output will be a file consisting of both parts, which can then be installed. This option is customarily used for files where settings have been modified by the user.

Choosing to view the diff(1) results again will show you the file differences just like mergemaster(8) did before prompting you for an option.

After mergemaster(8) is done with the system files you will be prompted for other options. mergemaster(8) may ask if you want to rebuild the password file and will finish up with an option to remove left-over temporary files.

23.4.11.2 Manual Update

If you wish to do the update manually, however, you cannot just copy over the files from /usr/src/etc to /etc and have it work. Some of these files must be ¡§installed¡¨ first. This is because the /usr/src/etc directory is not a copy of what your /etc directory should look like. In addition, there are files that should be in /etc that are not in /usr/src/etc.

If you are using mergemaster(8) (as recommended), you can skip forward to the next section.

The simplest way to do this by hand is to install the files into a new directory, and then work through them looking for differences.

Backup Your Existing /etc: Although, in theory, nothing is going to touch this directory automatically, it is always better to be sure. So copy your existing /etc directory somewhere safe. Something like:

# cp -Rp /etc /etc.old

-R does a recursive copy, -p preserves times, ownerships on files and suchlike.

You need to build a dummy set of directories to install the new /etc and other files into. /var/tmp/root is a reasonable choice, and there are a number of subdirectories required under this as well.

# mkdir /var/tmp/root
# cd /usr/src/etc
# make DESTDIR=/var/tmp/root distrib-dirs distribution

This will build the necessary directory structure and install the files. A lot of the subdirectories that have been created under /var/tmp/root are empty and should be deleted. The simplest way to do this is to:

# cd /var/tmp/root
# find -d . -type d | xargs rmdir 2>/dev/null

This will remove all empty directories. (Standard error is redirected to /dev/null to prevent the warnings about the directories that are not empty.)

/var/tmp/root now contains all the files that should be placed in appropriate locations below /. You now have to go through each of these files, determining how they differ with your existing files.

Note that some of the files that will have been installed in /var/tmp/root have a leading ¡§.¡¨. At the time of writing the only files like this are shell startup files in /var/tmp/root/ and /var/tmp/root/root/, although there may be others (depending on when you are reading this). Make sure you use ls -a to catch them.

The simplest way to do this is to use diff(1) to compare the two files:

# diff /etc/shells /var/tmp/root/etc/shells

This will show you the differences between your /etc/shells file and the new /var/tmp/root/etc/shells file. Use these to decide whether to merge in changes that you have made or whether to copy over your old file.

Name the New Root Directory (/var/tmp/root) with a Time Stamp, so You Can Easily Compare Differences Between Versions: Frequently rebuilding the world means that you have to update /etc frequently as well, which can be a bit of a chore.

You can speed this process up by keeping a copy of the last set of changed files that you merged into /etc. The following procedure gives one idea of how to do this.

  1. Make the world as normal. When you want to update /etc and the other directories, give the target directory a name based on the current date. If you were doing this on the 14th of February 1998 you could do the following:

    # mkdir /var/tmp/root-19980214
    # cd /usr/src/etc
    # make DESTDIR=/var/tmp/root-19980214 \
        distrib-dirs distribution
    
  2. Merge in the changes from this directory as outlined above.

    Do not remove the /var/tmp/root-19980214 directory when you have finished.

  3. When you have downloaded the latest version of the source and remade it, follow step 1. This will give you a new directory, which might be called /var/tmp/root-19980221 (if you wait a week between doing updates).

  4. You can now see the differences that have been made in the intervening week using diff(1) to create a recursive diff between the two directories:

    # cd /var/tmp
    # diff -r root-19980214 root-19980221
    

    Typically, this will be a much smaller set of differences than those between /var/tmp/root-19980221/etc and /etc. Because the set of differences is smaller, it is easier to migrate those changes across into your /etc directory.

  5. You can now remove the older of the two /var/tmp/root-* directories:

    # rm -rf /var/tmp/root-19980214
    
  6. Repeat this process every time you need to merge in changes to /etc.

You can use date(1) to automate the generation of the directory names:

# mkdir /var/tmp/root-`date "+%Y%m%d"`

23.4.12 Rebooting

You are now done. After you have verified that everything appears to be in the right place you can reboot the system. A simple shutdown(8) should do it:

# shutdown -r now

23.4.13 Finished

You should now have successfully upgraded your FreeBSD system. Congratulations.

If things went slightly wrong, it is easy to rebuild a particular piece of the system. For example, if you accidentally deleted /etc/magic as part of the upgrade or merge of /etc, the file(1) command will stop working. In this case, the fix would be to run:

# cd /usr/src/usr.bin/file
# make all install

23.4.14 Questions

23.4.14.1. Do I need to re-make the world for every change?
23.4.14.2. My compile failed with lots of signal 11 (or other signal number) errors. What has happened?
23.4.14.3. Can I remove /usr/obj when I have finished?
23.4.14.4. Can interrupted builds be resumed?
23.4.14.5. How can I speed up making the world?
23.4.14.6. What do I do if something goes wrong?

23.4.14.1. Do I need to re-make the world for every change?

There is no easy answer to this one, as it depends on the nature of the change. For example, if you just ran CVSup, and it has shown the following files as being updated:

src/games/cribbage/instr.c
src/games/sail/pl_main.c
src/release/sysinstall/config.c
src/release/sysinstall/media.c
src/share/mk/bsd.port.mk

it probably is not worth rebuilding the entire world. You could just go to the appropriate sub-directories and make all install, and that's about it. But if something major changed, for example src/lib/libc/stdlib then you should either re-make the world, or at least those parts of it that are statically linked (as well as anything else you might have added that is statically linked).

At the end of the day, it is your call. You might be happy re-making the world every fortnight say, and let changes accumulate over that fortnight. Or you might want to re-make just those things that have changed, and be confident you can spot all the dependencies.

And, of course, this all depends on how often you want to upgrade, and whether you are tracking FreeBSD-STABLE or FreeBSD-CURRENT.

23.4.14.2. My compile failed with lots of signal 11 (or other signal number) errors. What has happened?

This is normally indicative of hardware problems. (Re)making the world is an effective way to stress test your hardware, and will frequently throw up memory problems. These normally manifest themselves as the compiler mysteriously dying on receipt of strange signals.

A sure indicator of this is if you can restart the make and it dies at a different point in the process.

In this instance there is little you can do except start swapping around the components in your machine to determine which one is failing.

23.4.14.3. Can I remove /usr/obj when I have finished?

The short answer is yes.

/usr/obj contains all the object files that were produced during the compilation phase. Normally, one of the first steps in the make buildworld process is to remove this directory and start afresh. In this case, keeping /usr/obj around after you have finished makes little sense, and will free up a large chunk of disk space (currently about 340 MB).

However, if you know what you are doing you can have make buildworld skip this step. This will make subsequent builds run much faster, since most of sources will not need to be recompiled. The flip side of this is that subtle dependency problems can creep in, causing your build to fail in odd ways. This frequently generates noise on the FreeBSD mailing lists, when one person complains that their build has failed, not realizing that it is because they have tried to cut corners.

23.4.14.4. Can interrupted builds be resumed?

This depends on how far through the process you got before you found a problem.

In general (and this is not a hard and fast rule) the make buildworld process builds new copies of essential tools (such as gcc(1), and make(1)) and the system libraries. These tools and libraries are then installed. The new tools and libraries are then used to rebuild themselves, and are installed again. The entire system (now including regular user programs, such as ls(1) or grep(1)) is then rebuilt with the new system files.

If you are at the last stage, and you know it (because you have looked through the output that you were storing) then you can (fairly safely) do:

... fix the problem ...
# cd /usr/src
# make -DNO_CLEAN all

This will not undo the work of the previous make buildworld.

If you see the message:

--------------------------------------------------------------
Building everything..
--------------------------------------------------------------

in the make buildworld output then it is probably fairly safe to do so.

If you do not see that message, or you are not sure, then it is always better to be safe than sorry, and restart the build from scratch.

23.4.14.5. How can I speed up making the world?

  • Run in single user mode.

  • Put the /usr/src and /usr/obj directories on separate file systems held on separate disks. If possible, put these disks on separate disk controllers.

  • Better still, put these file systems across multiple disks using the ccd(4) (concatenated disk driver) device.

  • Turn off profiling (set ¡§NO_PROFILE=true¡¨ in /etc/make.conf). You almost certainly do not need it.

  • Also in /etc/make.conf, set CFLAGS to something like -O -pipe. The optimization -O2 is much slower, and the optimization difference between -O and -O2 is normally negligible. -pipe lets the compiler use pipes rather than temporary files for communication, which saves disk access (at the expense of memory).

  • Pass the -jn option to make(1) to run multiple processes in parallel. This usually helps regardless of whether you have a single or a multi processor machine.

  • The file system holding /usr/src can be mounted (or remounted) with the noatime option. This prevents the file system from recording the file access time. You probably do not need this information anyway.

    # mount -u -o noatime /usr/src
    

    Warning: The example assumes /usr/src is on its own file system. If it is not (if it is a part of /usr for example) then you will need to use that file system mount point, and not /usr/src.

  • The file system holding /usr/obj can be mounted (or remounted) with the async option. This causes disk writes to happen asynchronously. In other words, the write completes immediately, and the data is written to the disk a few seconds later. This allows writes to be clustered together, and can be a dramatic performance boost.

    Warning: Keep in mind that this option makes your file system more fragile. With this option there is an increased chance that, should power fail, the file system will be in an unrecoverable state when the machine restarts.

    If /usr/obj is the only thing on this file system then it is not a problem. If you have other, valuable data on the same file system then ensure your backups are fresh before you enable this option.

    # mount -u -o async /usr/obj
    

    Warning: As above, if /usr/obj is not on its own file system, replace it in the example with the name of the appropriate mount point.

23.4.14.6. What do I do if something goes wrong?

Make absolutely sure your environment has no extraneous cruft from earlier builds. This is simple enough.

# chflags -R noschg /usr/obj/usr
# rm -rf /usr/obj/usr
# cd /usr/src
# make cleandir
# make cleandir

Yes, make cleandir really should be run twice.

Then restart the whole process, starting with make buildworld.

If you still have problems, send the error and the output of uname -a to FreeBSD general questions ¶l»¼½×¾Â. Be prepared to answer other questions about your setup!

¥»¤å¤Î¨ä¥L¤å¥ó¡A¥i¥Ñ¦¹¤U¸ü¡Gftp://ftp.FreeBSD.org/pub/FreeBSD/doc/¡C

­Y¦³ FreeBSD ¤è­±ºÃ°Ý¡A½Ð¥ý¾\Ū FreeBSD ¬ÛÃö¤å¥ó¡A¦p¤£¯à¸Ñ¨Mªº¸Ü¡A¦A¬¢¸ß <questions@FreeBSD.org>¡C
Ãö©ó¥»¤å¥óªº°ÝÃD¡A½Ð¬¢¸ß <doc@FreeBSD.org>¡C