Lsb conforming init script
From PostgreSQL wiki
Jump to navigationJump to searchThis is to show an LSB conforming script done using sh scripting, so that it can be used to identify desirable features to add to pg_ctl.
Script
#<source lang="bash"> #! /bin/sh ### BEGIN INIT INFO # Provides: postgresql # Required-Start: $local_fs $network $syslog # Should-Start: $remote_fs $named $time # Required-Stop: $local_fs $network $syslog # Should-Stop: $remote_fs $named # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: PostgreSQL RDBMS # Description: PostgreSQL RDBMS service. # The world's most advanced open source database. # See http://www.postgresql.org/ for more information. ### END INIT INFO # This is an example of a Linux LSB conforming init script. # See http://refspecs.freestandards.org/ for more information on LSB. # Original author: Kevin Grittner # $PostgreSQL$ #-------------------------------------------------------------------- # The only edits needed should be in the INIT INFO block above # and between the lines of dashes below. If any other # changes are needed, or you find a way to enhance the script, # consider posting to the PostgreSQL hackers list. #-------------------------------------------------------------------- # Installation prefix prefix="/usr/local/pgsql" prefix="/usr/local/pgsql-8.5devel" # Data directory (Don't end with a slash.) PGDATA="/var/local/pgsql/data" PGDATA="/var/pgsql/data/test3" # Who to run the postmaster as, usually "postgres". (NOT "root") PGUSER=postgres PGUSER=kgrittn # Where to keep a log file PGLOG="$PGDATA/serverlog" #-------------------------------------------------------------------- # The path that is to be used for the script PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # The LSB functions must be present. lsbf=/lib/lsb/init-functions test -r "$lsbf" || { echo "$0: not able to read $lsbf: script cannot run" 1>&2 exit 5 } # Source the functions. . "$lsbf" # Most output from the script should be through the LSB msg functions after this. # In particular, messages indicating success, failure, or warning must use the LSB functions. # Progress information may be output to stdout or stderr; although it should be understood # that it might not be shown to the user or written to any log or file. # Define usage string, used in more than one place. usage="Usage: $0 {start|stop|restart|try-restart|reload|force-reload|status}" # Check that we have one parameter: action if [ $# -ne 1 ] ; then if [ $# -lt 1 -o "$1" = "" ] ; then log_failure_msg "$0: action not specified" else log_failure_msg "$0: too many parameters" fi log_warning_msg "$usage" exit 2 fi action="$1" # What to use to manipulate the postmaster. PGCTL="$prefix/bin/pg_ctl" # Only start if we can find the $PGCTL executable. test -x "$PGCTL" || { if [ "$action" = "stop" ] ; then log_warning_msg "$0: executable $PGCTL not found: $action request ignored" exit 0 else log_failure_msg "$0: executable $PGCTL not found: $action request failed" exit 5 fi } pidfile="$PGDATA/postmaster.pid" servicename=$( basename "$0" ) ulimit -c unlimited # Assuming the first line of the pid file contains (at most) one pid, return it. pg_initd_pid () { head -1 "$pidfile" 2>/dev/null } # Count how many processes named postgres* are using the data directory. pg_initd_process_count () { lsof -a -c postgres | grep "$PGDATA/" | wc -l } # Count how many streams are open for connecting to the pid, TCP and UNIX sockets. pg_initd_socket_count () { pgpid=$( pg_initd_pid ) if [ "$pgpid" = "" ] ; then echo "-1" else echo $(( $( lsof -at -p "$pgpid" -U | wc -l ) \ + $( lsof -a -p "$pgpid" -itcp | grep LISTEN | wc -l ) )) fi } pg_initd_start () { echo -n "Starting $servicename: " su -c "'$PGCTL' -w -D '$PGDATA' -l '$PGLOG' start" - $PGUSER rc=$? if [ $rc -ne 0 ] ; then return fi # pg_ctl can be fooled by a competing postmaster which has already grabbed the port; # the test initiated by -w can indicate success, based on talking to the other process. # Check that the pid we just created matches an open server socket of some sort. if [ $( pg_initd_socket_count ) -gt 0 ] ; then return fi log_warning_msg "$servicename $action: a competing instance of PostgreSQL may be running" rc=1 } pg_initd_stop () { # This will be called when the server is shutting down. # If this function never exits, the server hangs forever in a partially shut down state, # possibly requiring a hard reboot without shutting down other services. # If this function exits before PostgreSQL is completely shut down, any remaining # processes will probably be killed with -9 -- which is not recommended. # Try very hard to avoid either of the above. pgpid=$( pg_initd_pid ) if [ "$pgpid" = "" ] ; then # If this happens, the process went away after the initial check. echo "$servicename: not running" rc=0 return fi echo -n "Shutting down $servicename: " su -c "kill -s SIGINT '$pgpid'" - $PGUSER echo -n 'waiting for server to stop...' rc=1 # Try "fast" shutdown for a while. for seconds in $( seq 50 ) ; do echo -n '.' if ! ps -o pid= -p "$pgpid" >/dev/null ; then rc=0 break fi sleep 1 done # Fast didn't do it; try immediate shutdown. if [ $rc -ne 0 ] ; then su -c "kill -s SIGQUIT '$pgpid'" - $PGUSER for seconds in $( seq 10 ) ; do echo -n '!' if ! ps -o pid= -p "$pgpid" >/dev/null ; then rc=0 break fi sleep 1 done fi ! ps -o pid= -p "$pgpid" >/dev/null rc=$? if [ "$rc" -eq 0 ] ; then echo ' done' rm -f "$pidfile" else echo ' failed' fi } pg_initd_reload () { su -c "$PGCTL reload -D '$PGDATA'" - $PGUSER rc=$? } pg_initd_status () { if [ ! -f "$pidfile" ] ; then if [ $( pg_initd_process_count ) -ne 0 ] ; then log_warning_msg "$servicename $action: orphaned postgres processes may exist" rc=4 else rc=3 fi return fi # pid file found pgpid=$( pg_initd_pid ) if [ $( stat -c%U "$PGDATA" ) != "$PGUSER" ] ; then log_warning_msg "$servicename $action: data directory \"$PGDATA\" not owned by \"$PGUSER\"" rc=4 return fi su -c "$PGCTL status -D '$PGDATA'" - $PGUSER rc=$? if [ $rc -ne 0 ] ; then # pg_ctl doesn't return LSB conforming values; treat non-success as "unknown" failure. rc=4 fi } pg_initd_exit () { if [ "$action" = "status" ] ; then case $rc in 0) log_success_msg "$servicename $action: running" ;; 1) log_failure_msg "$servicename $action: dead with existing pid file: $pidfile" ;; 3) log_failure_msg "$servicename $action: not running" ;; *) log_failure_msg "$servicename $action: unknown ($rc)" ;; esac else case $rc in 0) log_success_msg "$servicename $action: done" ;; 1) log_failure_msg "$servicename $action: failed" ;; 4) log_failure_msg "$servicename $action: insufficient privilege" ;; 7) log_failure_msg "$servicename $action: not running" ;; *) log_failure_msg "$servicename $action: failed ($rc)" ;; esac fi exit $rc } # Actions other than status may use these return codes: # 1 - generic or unspecified error # 2 - invalid or excess argument(s) # 3 - unimplemented feature (for example, "reload") # 4 - user had insufficient privilege # 5 - program is not installed # 6 - program is not configured # 7 - program is not running # Some of these are tested before getting to this case statement. case "$action" in start) # Start the service. # If already running, return success without start attempt. pg_initd_status if [ $rc -eq 0 ] ; then log_warning_msg "$servicename $action: service already running; no action taken" pg_initd_exit fi pg_initd_start pg_initd_exit ;; stop) # Stop the service. # If not running, return success without stop attempt. pg_initd_status if [ $rc -eq 3 ] ; then log_warning_msg "$servicename $action: service not running; no action taken" rc=0 pg_initd_exit fi if [ $rc -ne 0 ] ; then rc=1 pg_initd_exit fi pg_initd_stop pg_initd_exit ;; restart) # Stop and restart the service if the service is already running, # otherwise start the service. pg_initd_status if [ $rc -eq 3 ] ; then log_warning_msg "$servicename $action: service not running; no attempt to stop" else pg_initd_stop if [ $rc -ne 0 ] ; then pg_initd_exit fi fi pg_initd_start pg_initd_exit ;; try-restart) # Restart the service if the service is already running. # If stopped, return success without stop attempt. pg_initd_status if [ $rc -eq 3 ] ; then log_warning_msg "$servicename $action: service not running; no action taken" rc=0 pg_initd_exit fi if [ $rc -ne 0 ] ; then pg_initd_exit fi pg_initd_stop if [ $rc -ne 0 ] ; then pg_initd_exit fi pg_initd_start pg_initd_exit ;; reload|force-reload) # Cause the configuration of the service to be reloaded # without actually stopping and restarting the service. # (Since PostgreSQL supports reload, force-reload should use that.) pg_initd_status if [ $rc -eq 3 ] ; then rc=7 pg_initd_exit fi pg_initd_reload pg_initd_exit ;; status) # Print the current status of the service. # Return codes differ from other actions: # 0 - program is running or service is OK # 1 - program is dead and /var/run pid file exists # 2 - program is dead and /var/lock lock file exists # 3 - program is not running # 4 - program or service status is unknown pg_initd_status pg_initd_exit ;; *) # If we don't recognize action, consider it an invalid argument. # If the standard adds actions we don't support, exit should be 3 for those. log_failure_msg "$0: action \"$action\" not recognized" log_warning_msg "$usage" exit 2 ;; esac