diff --git a/doc/guide.html b/doc/guide.html
index 6b4be6e3a..02c5c94cd 100644
--- a/doc/guide.html
+++ b/doc/guide.html
@@ -3280,6 +3280,8 @@ all the environment variables and command line parameters.
The environment
Path to the directory with binary system libraries.
EJABBERD_DOC_PATH
Path to the directory with ejabberd documentation.
+EJABBERD_PID_PATH
+ Path to the PID file that ejabberd can create when started.
HOME
Path to the directory that is considered ejabberd’s home.
This path is used to read the file .erlang.cookie.
diff --git a/doc/guide.tex b/doc/guide.tex
index 43110aad9..74d6fa8b4 100644
--- a/doc/guide.tex
+++ b/doc/guide.tex
@@ -4210,6 +4210,8 @@ The environment variables:
Path to the directory with binary system libraries.
\titem{EJABBERD\_DOC\_PATH}
Path to the directory with ejabberd documentation.
+ \titem{EJABBERD\_PID\_PATH}
+ Path to the PID file that ejabberd can create when started.
\titem{HOME}
Path to the directory that is considered \ejabberd{}'s home.
This path is used to read the file \term{.erlang.cookie}.
diff --git a/src/ejabberd.erl b/src/ejabberd.erl
index 0c7c56a2a..228614b93 100644
--- a/src/ejabberd.erl
+++ b/src/ejabberd.erl
@@ -28,6 +28,7 @@
-author('alexey@process-one.net').
-export([start/0, stop/0,
+ get_pid_file/0,
get_so_path/0, get_bin_path/0]).
start() ->
@@ -63,3 +64,14 @@ get_bin_path() ->
Path ->
Path
end.
+
+%% @spec () -> false | string()
+get_pid_file() ->
+ case os:getenv("EJABBERD_PID_PATH") of
+ false ->
+ false;
+ "" ->
+ false;
+ Path ->
+ Path
+ end.
diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl
index c68199d19..bea1b0b7a 100644
--- a/src/ejabberd_app.erl
+++ b/src/ejabberd_app.erl
@@ -40,6 +40,7 @@
start(normal, _Args) ->
ejabberd_loglevel:set(4),
+ write_pid_file(),
application:start(sasl),
application:start(exmpp),
randoms:start(),
@@ -81,6 +82,7 @@ prep_stop(State) ->
%% All the processes were killed when this function is called
stop(_State) ->
?INFO_MSG("ejabberd ~s is stopped in the node ~p", [?VERSION, node()]),
+ delete_pid_file(),
ejabberd_debug:stop(),
ok.
@@ -182,3 +184,34 @@ add_windows_nameservers() ->
IPTs = win32_dns:get_nameservers(),
?INFO_MSG("Adding machine's DNS IPs to Erlang system:~n~p", [IPTs]),
lists:foreach(fun(IPT) -> inet_db:add_ns(IPT) end, IPTs).
+
+
+%%%
+%%% PID file
+%%%
+
+write_pid_file() ->
+ case ejabberd:get_pid_file() of
+ false ->
+ ok;
+ PidFilename ->
+ write_pid_file(os:getpid(), PidFilename)
+ end.
+
+write_pid_file(Pid, PidFilename) ->
+ case file:open(PidFilename, [write]) of
+ {ok, Fd} ->
+ io:format(Fd, "~s~n", [Pid]),
+ file:close(Fd);
+ {error, Reason} ->
+ ?ERROR_MSG("Cannot write PID file ~s~nReason: ~p", [PidFilename, Reason]),
+ throw({cannot_write_pid_file, PidFilename, Reason})
+ end.
+
+delete_pid_file() ->
+ case ejabberd:get_pid_file() of
+ false ->
+ ok;
+ PidFilename ->
+ file:delete(PidFilename)
+ end.
diff --git a/src/ejabberdctl.cfg.example b/src/ejabberdctl.cfg.example
index 0c8d0c5a6..1ba413fe2 100644
--- a/src/ejabberdctl.cfg.example
+++ b/src/ejabberdctl.cfg.example
@@ -110,6 +110,18 @@
#
#ERLANG_NODE=ejabberd
+#.
+#' EJABBERD_PID_PATH: ejabberd PID file
+#
+# Indicate the full path to the ejabberd Process identifier (PID) file.
+# If this variable is defined, ejabberd writes the PID file when starts,
+# and deletes it when stops.
+# Remember to create the directory and grant write permission to ejabberd.
+#
+# Default: don't write PID file
+#
+#EJABBERD_PID_PATH=/var/run/ejabberd/ejabberd.pid
+
#.
#'
# vim: foldmarker=#',#. foldmethod=marker:
diff --git a/src/ejabberdctl.template b/src/ejabberdctl.template
index f6a30bb09..48a56ba5b 100644
--- a/src/ejabberdctl.template
+++ b/src/ejabberdctl.template
@@ -118,6 +118,7 @@ export EJABBERD_LOG_PATH
export EJABBERD_SO_PATH
export EJABBERD_BIN_PATH
export EJABBERD_DOC_PATH
+export EJABBERD_PID_PATH
export ERL_CRASH_DUMP
export ERL_INETRC
export ERL_MAX_PORTS