Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
release_handler(3)	   Erlang Module Definition	    release_handler(3)

NAME
       release_handler - Unpacking and Installation of Release Packages

DESCRIPTION
       The  release  handler  is  a  process belonging to the SASL application
       which is	responsible for	release	handling, that is, unpacking,  instal-
       lation, and removal of release packages.

       An introduction to release handling and a usage example can be found in
       Design Principles.

       A release package is a compressed tar file containing code for  a  cer-
       tain  version  of  a release, created by	calling	systools:make_tar/1,2.
       The release package should be placed in the $ROOT/releases directory of
       the  previous  version  of  the release where $ROOT is the installation
       root directory, code:root_dir().	 Another  releases  directory  can  be
       specified  using	 the SASL configuration	parameter releases_dir,	or the
       OS environment variable RELDIR. The release handler must	have write ac-
       cess to this directory in order to install the new release. The persis-
       tent state of the release handler is stored there in a file called  RE-
       LEASES.

       A  release  package  should  always  contain  the release resource file
       Name.rel	and a boot script Name.boot. It	may contain a release  upgrade
       file  relup  and	 a system configuration	file sys.config. The .rel file
       contains	information about the release: its name,  version,  and	 which
       ERTS  and application versions it uses. The relup file contains scripts
       for how to upgrade to, or downgrade from, this version of the release.

       The release package can be unpacked, which extracts the files.  An  un-
       packed  release can be installed. The currently used version of the re-
       lease is	then upgraded or downgraded to the specified version by	evalu-
       ating  the instructions in relup. An installed release can be made per-
       manent. There can only be one permanent release in the system, and this
       is  the	release	 that is used if the system is restarted. An installed
       release,	except the permanent one, can be removed. When	a  release  is
       removed,	all files that belong to that release only are deleted.

       Each  version  of the release has a status. The status can be unpacked,
       current,	permanent, or old. There is always one	latest	release	 which
       either  has  status permanent (normal case), or current (installed, but
       not yet made permanent).	The following table illustrates	the meaning of
       the status values:

       Status	  Action		NextStatus
       -------------------------------------------
	 -	  unpack		unpacked
       unpacked	  install		current
		  remove		  -
       current	  make_permanent	permanent
		  install other		old
		  remove		  -
       permanent  make other permanent	old
		  install		permanent
       old	  reboot_old		permanent
		  install		current
		  remove		  -

       The  release  handler  process  is a locally registered process on each
       node. When a release is installed in a distributed system, the  release
       handler	on  each  node must be called. The release installation	may be
       synchronized between nodes. From	an operator view, it may  be  unsatis-
       factory to specify each node. The aim is	to install one release package
       in the system, no matter	how many nodes there are. If this is the case,
       it  is recommended that software	management functions are written which
       take care of this problem. Such a function may have  knowledge  of  the
       system  architecture, so	it can contact each individual release handler
       to install the package.

       For release handling to work properly, the runtime system needs to have
       knowledge  about	which release it is currently running. It must also be
       able to change (in run-time) which boot script and system configuration
       file  should  be	used if	the system is restarted. This is taken care of
       automatically if	Erlang is started as an	embedded  system.  Read	 about
       this  in	 Embedded  System. In this case, the system configuration file
       sys.config is mandatory.

       The installation	of a new release may restart the system. Which program
       to use is specified by the SASL configuration parameter start_prg which
       defaults	to $ROOT/bin/start.

       The emulator restart on Windows NT expects that the system  is  started
       using  the  erlsrv program (as a	service). Furthermore the release han-
       dler expects that the service is	named NodeName_Release,	where NodeName
       is  the first part of the Erlang	nodename (up to, but not including the
       "@") and	Release	is the current version of  the	release.  The  release
       handler furthermore expects that	a program like start_erl.exe is	speci-
       fied as "machine" to erlsrv. During upgrading with restart, a new  ser-
       vice will be registered and started. The	new service will be set	to au-
       tomatic and the old service removed as soon as the new release is  made
       permanent.

       The release handler at a	node which runs	on a diskless machine, or with
       a read-only file	system,	must be	configured accordingly using the  fol-
       lowing sasl configuration parameters (see sasl(6) for details):

	 masters:
	   This	node uses a number of master nodes in order to store and fetch
	   release information.	All master nodes must be up and	running	 when-
	   ever	release	information is written by this node.

	 client_directory:
	   The client_directory	in the directory structure of the master nodes
	   must	be specified.

	 static_emulator:
	   This	parameter specifies if the Erlang emulator is  statically  in-
	   stalled  at	the  client node. A node with a	static emulator	cannot
	   dynamically switch to a new emulator	because	the  executable	 files
	   are statically written into memory.

       It  is  also  possible to use the release handler to unpack and install
       release packages	when not running Erlang	as an embedded system, but  in
       this case the user must somehow make sure that correct boot scripts and
       configuration files are used if the system needs	to be restarted.

       There are additional functions for using	another	 file  structure  than
       the structure defined in	OTP. These functions can be used to test a re-
       lease upgrade locally.

EXPORTS
       check_install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}
       check_install_release(Vsn,Opts) -> {ok, OtherVsn, Descr}	| {error, Rea-
       son}

	      Types:

		 Vsn = OtherVsn	= string()
		 Opts =	[Opt]
		 Opt = purge
		 Descr = term()
		 Reason	= term()

	      Checks  if  the  specified version Vsn of	the release can	be in-
	      stalled. The release must	not have status	current. Issues	 warn-
	      ings  if	relup  or  sys.config  are  not	 present.  If relup is
	      present, its contents are	checked	and {error,Reason} is returned
	      if an error is found. Also checks	that all required applications
	      are present and that all new code	can be loaded, or  {error,Rea-
	      son} is returned.

	      This  function  evaluates	all instructions that occur before the
	      point_of_no_return instruction in	the release upgrade script.

	      Returns the same as install_release/1. Descr defaults to	""  if
	      no relup file is found.

	      If  the  option  purge  is  given, all old code that can be soft
	      purged will be purged after all other  checks  are  successfully
	      completed. This can be useful in order to	reduce the time	needed
	      by install_release.

       create_RELEASES(Root, RelDir, RelFile, AppDirs) -> ok | {error, Reason}

	      Types:

		 Root =	RelDir = RelFile = string()
		 AppDirs = [{App, Vsn, Dir}]
		  App =	atom()
		  Vsn =	Dir = string()
		 Reason	= term()

	      Creates an initial RELEASES file to be used by the release  han-
	      dler. This file must exist in order to install new releases.

	      Root is the root of the installation ($ROOT) as described	above.
	      RelDir is	the the	directory where	the RELEASES  file  should  be
	      created  (normally  $ROOT/releases).  RelFile is the name	of the
	      .rel file	that describes the initial release, including the  ex-
	      tension .rel.

	      AppDirs  can  be	used to	specify	from where the modules for the
	      specified	applications should be loaded. App is the name	of  an
	      application,  Vsn	is the version,	and Dir	is the name of the di-
	      rectory where App-Vsn  is	 located.  The	corresponding  modules
	      should  be  located  under Dir/App-Vsn/ebin. The directories for
	      applications not specified in AppDirs are	assumed	to be  located
	      in $ROOT/lib.

       install_file(Vsn, File) -> ok | {error, Reason}

	      Types:

		 Vsn = File = string()
		 Reason	= term()

	      Installs	a  release  dependent file in the release structure. A
	      release dependent	file is	a file that must  be  in  the  release
	      structure	when a new release is installed: start.boot, relup and
	      sys.config.

	      The function can be called, for example, when  these  files  are
	      generated	 at  the  target.  It  should  be called after set_un-
	      packed/2 has been	called.

       install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}
       install_release(Vsn, [Opt]) -> {ok, OtherVsn,  Descr}  |	 {continue_af-
       ter_restart, OtherVsn, Descr} | {error, Reason}

	      Types:

		 Vsn = OtherVsn	= string()
		 Opt = {error_action, Action} |	{code_change_timeout, Timeout}
		  | {suspend_timeout, Timeout} | {update_paths,	Bool}
		  Action = restart | reboot
		  Timeout = default | infinity | int()>0
		  Bool = boolean()
		 Descr = term()
		 Reason	 =  {illegal_option, Opt} | {already_installed,	Vsn} |
		 {change_appl_data,  term()}  |	 {missing_base_app,  OtherVsn,
		 App} |	{could_not_create_hybrid_boot, term()} | term()
		 App = atom()

	      Installs	the  specified version Vsn of the release. Looks first
	      for a relup file for Vsn and a script {UpFromVsn,Descr1,Instruc-
	      tions1}  in this file for	upgrading from the current version. If
	      not found, the function looks for	a relup	file for  the  current
	      version and a script {Vsn,Descr2,Instructions2} in this file for
	      downgrading to Vsn.

	      If a script is found, the	first thing that happens is  that  the
	      applications  specifications  are	 updated according to the .app
	      files and	sys.config belonging to	the release version Vsn.

	      After the	application specifications have	been updated, the  in-
	      structions  in the script	are evaluated and the function returns
	      {ok,OtherVsn,Descr} if successful. OtherVsn and  Descr  are  the
	      version (UpFromVsn or Vsn) and description (Descr1 or Descr2) as
	      specified	in the script.

	      If {continue_after_restart,OtherVsn,Descr} is returned, it means
	      that  the	emulator will be restarted before the upgrade instruc-
	      tions are	executed. This will happen if the emulator or  any  of
	      the  applications	 kernel,  stdlib  or sasl are updated. The new
	      version of the emulator and these	core applications will execute
	      after  the  restart, but for all other applications the old ver-
	      sions will be started and	the upgrade will be performed as  nor-
	      mal by executing the upgrade instructions.

	      If  a recoverable	error occurs, the function returns {error,Rea-
	      son} and the original application	specifications	are  restored.
	      If a non-recoverable error occurs, the system is restarted.

	      The  option error_action defines if the node should be restarted
	      (init:restart()) or rebooted (init:reboot()) in case of an error
	      during the installation. Default is restart.

	      The option code_change_timeout defines the timeout for all calls
	      to sys:change_code. If no	 value	is  specified  or  default  is
	      given, the default value defined in sys is used.

	      The  option suspend_timeout defines the timeout for all calls to
	      sys:suspend. If no value is specified, the values	defined	by the
	      Timeout  parameter  of  the  upgrade or suspend instructions are
	      used. If default is specified, the default value defined in  sys
	      is used.

	      The option {update_paths,Bool} indicates if all application code
	      paths should be updated (Bool==true), or if only code paths  for
	      modified	applications should be updated (Bool==false, default).
	      This option only has effect for  other  application  directories
	      than  the	default	$ROOT/lib/App-Vsn, that	is, application	direc-
	      tories provided in the AppDirs argument in a call	to  create_RE-
	      LEASES/4 or set_unpacked/2.

	      Example:	In the current version CurVsn of a release, the	appli-
	      cation directory of myapp	is $ROOT/lib/myapp-1.0.	A new  version
	      NewVsn  is unpacked outside the release handler, and the release
	      handler is informed about	this with a call to:

	      release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
	      => {ok,NewVsn}

	      If NewVsn	is installed with the option {update_paths,true},  af-
	      terwards code:lib_dir(myapp) will	return /home/user/myapp-1.0.

	  Note:
	      Installing  a new	release	might be quite time consuming if there
	      are many processes in  the  system.  The	reason	is  that  each
	      process must be checked for references to	old code before	a mod-
	      ule can be purged. This check might lead to garbage  collections
	      and copying of data.

	      If  you  wish to speed up	the execution of install_release, then
	      you may  call  check_install_release  first,  using  the	option
	      purge.  This will	do the same check for old code,	and then purge
	      all modules that can be soft purged.  The	 purged	 modules  will
	      then  no	longer have any	old code, and install_release will not
	      need to do the checks.

	      Obviously, this will not reduce the overall  time	 for  the  up-
	      grade,  but it will allow	checks and purge to be executed	in the
	      background before	the real upgrade is started.

	  Note:
	      When upgrading the emulator from a version older than  OTP  R15,
	      there  will be an	attempt	to load	new application	beam code into
	      the old emulator.	In some	cases, the new beam format can not  be
	      read  by the old emulator, and so	the code loading will fail and
	      terminate	the complete upgrade. To overcome  this	 problem,  the
	      new  application	code should be compiled	with the old emulator.
	      See Design Principles for	more information  about	 emulator  up-
	      grade from pre OTP R15 versions.

       make_permanent(Vsn) -> ok | {error, Reason}

	      Types:

		 Vsn = string()
		 Reason	= {bad_status, Status} | term()

	      Makes the	specified version Vsn of the release permanent.

       remove_release(Vsn) -> ok | {error, Reason}

	      Types:

		 Vsn = string()
		 Reason	= {permanent, Vsn} | client_node | term()

	      Removes  a  release  and	its files from the system. The release
	      must not be the permanent	release. Removes only  the  files  and
	      directories not in use by	another	release.

       reboot_old_release(Vsn) -> ok | {error, Reason}

	      Types:

		 Vsn = string()
		 Reason	= {bad_status, Status} | term()

	      Reboots  the  system  by	making	the old	release	permanent, and
	      calls init:reboot() directly. The	release	must have status old.

       set_removed(Vsn)	-> ok |	{error,	Reason}

	      Types:

		 Vsn = string()
		 Reason	= {permanent, Vsn} | term()

	      Makes it possible	to handle removal of releases outside the  re-
	      lease handler. Tells the release handler that the	release	is re-
	      moved from the system. This function does	not delete any files.

       set_unpacked(RelFile, AppDirs) -> {ok, Vsn} | {error, Reason}

	      Types:

		 RelFile = string()
		 AppDirs = [{App, Vsn, Dir}]
		  App =	atom()
		  Vsn =	Dir = string()
		 Reason	= term()

	      Makes it possible	to handle unpacking of	releases  outside  the
	      release  handler.	 Tells the release handler that	the release is
	      unpacked.	Vsn  is	 extracted  from  the  release	resource  file
	      RelFile.

	      AppDirs  can  be	used to	specify	from where the modules for the
	      specified	applications should be loaded. App is the name	of  an
	      application,  Vsn	is the version,	and Dir	is the name of the di-
	      rectory where App-Vsn  is	 located.  The	corresponding  modules
	      should  be  located  under Dir/App-Vsn/ebin. The directories for
	      applications not specified in AppDirs are	assumed	to be  located
	      in $ROOT/lib.

       unpack_release(Name) -> {ok, Vsn} | {error, Reason}

	      Types:

		 Name =	Vsn = string()
		 Reason	= client_node |	term()

	      Unpacks  a  release  package Name.tar.gz located in the releases
	      directory.

	      Performs some checks on the package - for	 example  checks  that
	      all mandatory files are present -	and extracts its contents.

       which_releases()	-> [{Name, Vsn,	Apps, Status}]

	      Types:

		 Name =	Vsn = string()
		 Apps =	["App-Vsn"]
		 Status	= unpacked | current | permanent | old

	      Returns all releases known to the	release	handler.

       which_releases(Status) -> [{Name, Vsn, Apps, Status}]

	      Types:

		 Name =	Vsn = string()
		 Apps =	["App-Vsn"]
		 Status	= unpacked | current | permanent | old

	      Returns  all releases known to the release handler of a specific
	      status.

APPLICATION UPGRADE/DOWNGRADE
       The following functions can be used to test upgrade  and	 downgrade  of
       single  applications  (instead  of  upgrading/downgrading an entire re-
       lease). A script	corresponding to relup is created on-the-fly, based on
       the  .appup file	for the	application, and evaluated exactly in the same
       way as release_handler does.

   Warning:
       These functions are primarily intended for simplified testing of	.appup
       files.  They  are  not  run  within  the	context	of the release_handler
       process.	They must therefore not	be used	together  with	calls  to  in-
       stall_release/1,2,  as  this will cause release_handler to end up in an
       inconsistent state.

       No persistent information is updated, why these functions can  be  used
       on  any	Erlang node, embedded or not. Also, using these	functions does
       not affect which	code will be loaded in case of a reboot.

       If the upgrade or downgrade fails, the application may end up in	an in-
       consistent state.

EXPORTS
       upgrade_app(App,	 Dir)  ->  {ok,	Unpurged} | restart_emulator | {error,
       Reason}

	      Types:

		 App = atom()
		 Dir = string()
		 Unpurged = [Module]
		  Module = atom()
		 Reason	= term()

	      Upgrades an application App from the current version  to	a  new
	      version located in Dir according to the .appup script.

	      App  is  the name	of the application, which must be started. Dir
	      is the new library directory of App, the	corresponding  modules
	      as  well	as  the	 .app and .appup files should be located under
	      Dir/ebin.

	      The function looks in the	.appup file and	tries to find  an  up-
	      grade  script  from the current version of the application using
	      upgrade_script/2.	 This  script  is  evaluated  using   eval_ap-
	      pup_script/4,  exactly  in  the  same way	as install_release/1,2
	      does.

	      Returns {ok, Unpurged} if	evaluating the script  is  successful,
	      where  Unpurged is a list	of unpurged modules, or	restart_emula-
	      tor if this instruction is encountered in	the script, or {error,
	      Reason}  if  an  error  occurred	when finding or	evaluating the
	      script.

	      If the restart_new_emulator instruction is found in the  script,
	      upgrade_app/2 will return	{error,restart_new_emulator}. The rea-
	      son for this is that this	instruction requires that a  new  ver-
	      sion  of	the emulator is	started	before the rest	of the upgrade
	      instructions can be executed, and	this can only be done  by  in-
	      stall_release/1,2.

       downgrade_app(App, Dir) ->
       downgrade_app(App,  OldVsn, Dir)	-> {ok,	Unpurged} | restart_emulator |
       {error, Reason}

	      Types:

		 App = atom()
		 Dir = OldVsn =	string()
		 Unpurged = [Module]
		  Module = atom()
		 Reason	= term()

	      Downgrades an application	App from the current version to	a pre-
	      vious  version  OldVsn  located  in  Dir according to the	.appup
	      script.

	      App is the name of the application, which	must be	started.  Old-
	      Vsn  is the previous version of the application and can be omit-
	      ted if Dir is of the format "App-OldVsn".	Dir is the library di-
	      rectory  of this previous	version	of App,	the corresponding mod-
	      ules as well as the  old	.app  file  should  be	located	 under
	      Dir/ebin.	 The  .appup file should be located in the ebin	direc-
	      tory  of	the  current  library  directory  of  the  application
	      (code:lib_dir(App)).

	      The function looks in the	.appup file and	tries to find an down-
	      grade script to the previous version of  the  application	 using
	      downgrade_script/3.  This	 script	 is  evaluated	using eval_ap-
	      pup_script/4, exactly in the  same  way  as  install_release/1,2
	      does.

	      Returns  {ok,  Unpurged} if evaluating the script	is successful,
	      where Unpurged is	a list of unpurged modules, or	restart_emula-
	      tor if this instruction is encountered in	the script, or {error,
	      Reason} if an error occurred  when  finding  or  evaluating  the
	      script.

       upgrade_script(App, Dir)	-> {ok,	NewVsn,	Script}

	      Types:

		 App = atom()
		 Dir = string()
		 NewVsn	= string()
		 Script	= Instructions -- see appup(4)

	      Tries  to	 find  an  application upgrade script for App from the
	      current version to a new version located in Dir.

	      The  upgrade  script  can	 then  be  evaluated  using   eval_ap-
	      pup_script/4.  It	 is  recommended to use	upgrade_app/2 instead,
	      but this function	is useful in order to inspect the contents  of
	      the script.

	      App  is  the name	of the application, which must be started. Dir
	      is the new library directory of App, the	corresponding  modules
	      as  well	as  the	 .app and .appup files should be located under
	      Dir/ebin.

	      The function looks in the	.appup file and	tries to find  an  up-
	      grade  script from the current version of	the application. High-
	      level instructions are translated	to low-level instructions  and
	      the  instructions	are sorted in the same manner as when generat-
	      ing a relup script.

	      Returns {ok, NewVsn, Script} if successful, where	NewVsn is  the
	      new application version.

	      Failure: If a script cannot be found, the	function fails with an
	      appropriate error	reason.

       downgrade_script(App, OldVsn, Dir) -> {ok, Script}

	      Types:

		 App = atom()
		 OldVsn	= Dir =	string()
		 Script	= Instructions -- see appup(4)

	      Tries to find an application downgrade script for	App  from  the
	      current version to a previous version OldVsn located in Dir.

	      The  downgrade  script  can  then	 be  evaluated	using eval_ap-
	      pup_script/4. It is recommended  to  use	downgrade_app/2,3  in-
	      stead,  but this function	is useful in order to inspect the con-
	      tents of the script.

	      App is the name of the application, which	must be	 started.  Dir
	      is the previous library directory	of App,	the corresponding mod-
	      ules as well as the  old	.app  file  should  be	located	 under
	      Dir/ebin.	 The  .appup file should be located in the ebin	direc-
	      tory  of	the  current  library  directory  of  the  application
	      (code:lib_dir(App)).

	      The function looks in the	.appup file and	tries to find an down-
	      grade script from	the current version of the application.	 High-
	      level  instructions are translated to low-level instructions and
	      the instructions are sorted in the same manner as	when  generat-
	      ing a relup script.

	      Returns {ok, Script} if successful.

	      Failure: If a script cannot be found, the	function fails with an
	      appropriate error	reason.

       eval_appup_script(App,  ToVsn,  ToDir,  Script)	->  {ok,  Unpurged}  |
       restart_emulator	| {error, Reason}

	      Types:

		 App = atom()
		 ToVsn = ToDir = string()
		 Script	-- see upgrade_script/2, downgrade_script/3
		 Unpurged = [Module]
		  Module = atom()
		 Reason	= term()

	      Evaluates	an application upgrade or downgrade script Script, the
	      result from calling upgrade_script/2 or downgrade_script/3,  ex-
	      actly in the same	way as install_release/1,2 does.

	      App is the name of the application, which	must be	started. ToVsn
	      is the version to	be upgraded/downgraded to, and	ToDir  is  the
	      library  directory of this version. The corresponding modules as
	      well as the .app	and  .appup  files  should  be	located	 under
	      Dir/ebin.

	      Returns  {ok,  Unpurged} if evaluating the script	is successful,
	      where Unpurged is	a list of unpurged modules, or	restart_emula-
	      tor if this instruction is encountered in	the script, or {error,
	      Reason} if an error occurred when	evaluating the script.

	      If the restart_new_emulator instruction is found in the  script,
	      eval_appup_script/4  will	 return	 {error,restart_new_emulator}.
	      The reason for this is that this instruction requires that a new
	      version  of  the	emulator is started before the rest of the up-
	      grade instructions can be	executed, and this can only be done by
	      install_release/1,2.

TYPICAL	ERROR REASONS
	 * {bad_masters, Masters} - The	master nodes Masters are not alive.

	 * {bad_rel_file, File}	- Specified .rel file File can not be read, or
	   does	not contain a single term.

	 * {bad_rel_data, Data}	- Specified .rel file does not contain a  rec-
	   ognized release specification, but another term Data.

	 * {bad_relup_file,  File}  -  Specified relup file Relup contains bad
	   data.

	 * {cannot_extract_file, Name, Reason} - Problems when extracting from
	   a tar file, erl_tar:extract/2 returned {error, {Name, Reason}}.

	 * {existing_release,  Vsn} - Specified	release	version	Vsn is already
	   in use.

	 * {Master, Reason, When} - Some  operation,  indicated	 by  the  term
	   When,  failed  on  the  master node Master with the specified error
	   reason Reason.

	 * {no_matching_relup, Vsn, CurrentVsn}	- Cannot  find	a  script  for
	   up/downgrading between CurrentVsn and Vsn.

	 * {no_such_directory, Path} - The directory Path does not exist.

	 * {no_such_file,  Path}  - The	path Path (file	or directory) does not
	   exist.

	 * {no_such_file, {Master, Path}} - The	path Path (file	or  directory)
	   does	not exist at the master	node Master.

	 * {no_such_release,  Vsn}  - The specified version Vsn	of the release
	   does	not exist.

	 * {not_a_directory, Path} - Path exists, but is not a directory.

	 * {Posix, File} - Some	file operation failed for File.	 Posix	is  an
	   atom	 named	from  the Posix	error codes, such as enoent, eacces or
	   eisdir. See file(3).

	 * Posix - Some	file operation failed, as above.

SEE ALSO
       OTP Design Principles, config(4), relup(4), rel(4), script(4),  sys(3),
       systools(3)

Ericsson AB			  sasl 2.4.1		    release_handler(3)

NAME | DESCRIPTION | EXPORTS | APPLICATION UPGRADE/DOWNGRADE | EXPORTS | TYPICAL ERROR REASONS | SEE ALSO

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=release_handler&sektion=3&manpath=FreeBSD+12.1-RELEASE+and+Ports>

home | help