3 # This is a "library" of sorts for use by the other FRR shell scripts. It
4 # has most of the daemon start/stop logic, but expects the following shell
5 # functions/commands to be provided by the "calling" script:
11 # (coincidentally, these are LSB standard functions.)
13 # Sourcing this file in a shell script will load FRR config variables but
14 # not perform any action. Note there is an "exit 1" if the main config
15 # file does not exist.
17 # This script should be installed in @CFG_SBIN@/frrcommon.sh
19 PATH
=/bin
:/usr
/bin
:/sbin
:/usr
/sbin
20 D_PATH
="@CFG_SBIN@" # /usr/lib/frr
21 C_PATH
="@CFG_SYSCONF@" # /etc/frr
22 V_PATH
="@CFG_STATE@" # /var/run/frr
23 VTYSH
="@vtysh_bin@" # /usr/bin/vtysh
24 FRR_USER
="@enable_user@" # frr
25 FRR_GROUP
="@enable_group@" # frr
26 FRR_VTY_GROUP
="@enable_vty_group@" # frrvty
28 # ORDER MATTERS FOR $DAEMONS!
30 # - watchfrr does NOT belong in this list
32 DAEMONS
="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd"
33 RELOAD_SCRIPT
="$D_PATH/frr-reload.py"
40 [ -n "$watchfrr_debug" ] ||
return 0
42 printf '%s %s(%s):' "`date +%Y-%m-%dT%H:%M:%S.%N`" "$0" $$
>&2
43 # this is to show how arguments are split regarding whitespace & co.
44 # (e.g. for use with `debug "message" "$@"`)
45 while [ $# -gt 0 ]; do
46 printf ' "%s"' "$1" >&2
53 [ -n "$FRR_USER" ] && chown
"$FRR_USER" "$1"
54 [ -n "$FRR_GROUP" ] && chgrp
"$FRR_GROUP" "$1"
58 [ "$1" = "watchfrr" ] && return 0
59 [ -r "$C_PATH/frr.conf" ] ||
return 0
61 "$VTYSH" -b -n -d "$1"
68 # note this sets global variables ($dmninst, $daemon, $inst)
70 daemon
="${dmninst%-*}"
72 [ "$daemon" != "$dmninst" ] && inst
="${dmninst#*-}"
76 # note $1 and $2 specify names for global variables to be set
77 local enabled disabled evar dvar
83 for daemon
in $DAEMONS; do
85 eval inst
=\$
${daemon}_instances
86 [ "$daemon" = zebra
-o "$daemon" = staticd
] && cfg
=yes
87 if [ -n "$cfg" -a "$cfg" != "no" -a "$cfg" != "0" ]; then
88 if ! daemon_prep
"$daemon" "$inst"; then
91 debug
"$daemon enabled"
92 enabled
="$enabled $daemon"
93 if [ -n "$inst" ]; then
94 debug
"$daemon multi-instance $inst"
98 enabled
="$enabled $daemon-$i"
103 debug
"$daemon disabled"
104 disabled
="$disabled $daemon"
108 enabled
="${enabled# }"
109 disabled
="${disabled# }"
110 [ -z "$evar" ] && echo "$enabled"
111 [ -n "$evar" ] && eval $evar="\"$enabled\""
112 [ -n "$dvar" ] && eval $dvar="\"$disabled\""
116 # individual daemon management
120 local daemon inst cfg
123 [ "$daemon" = "watchfrr" ] && return 0
124 [ -x "$D_PATH/$daemon" ] ||
{
125 log_failure_msg
"cannot start $daemon${inst:+ (instance $inst)}: daemon binary not installed"
128 [ -r "$C_PATH/frr.conf" ] && return 0
130 cfg
="$C_PATH/$daemon${inst:+-$inst}.conf"
131 if [ ! -r "$cfg" ]; then
139 local dmninst daemon inst args instopt wrap bin
142 ulimit -n $MAX_FDS > /dev
/null
2> /dev
/null
143 daemon_prep
"$daemon" "$inst" ||
return 1
144 if test ! -d "$V_PATH"; then
149 eval wrap
="\$${daemon}_wrap"
150 bin
="$D_PATH/$daemon"
151 instopt
="${inst:+-n $inst}"
152 eval args
="\$${daemon}_options"
154 if eval "$all_wrap $wrap $bin -d $instopt $args"; then
155 log_success_msg
"Started $dmninst"
158 log_failure_msg
"Failed to start $dmninst!"
163 local dmninst daemon inst pidfile vtyfile pid cnt fail
166 pidfile
="$V_PATH/$daemon${inst:+-$inst}.pid"
167 vtyfile
="$V_PATH/$daemon${inst:+-$inst}.vty"
169 [ -r "$pidfile" ] || fail
="pid file not found"
170 [ -z "$fail" ] && pid
="`cat \"$pidfile\"`"
171 [ -z "$fail" -a -z "$pid" ] && fail
="pid file is empty"
172 [ -n "$fail" ] ||
kill -0 "$pid" 2>/dev
/null || fail
="pid $pid not running"
174 if [ -n "$fail" ]; then
175 log_failure_msg
"Cannot stop $dmninst: $fail"
182 while kill -0 "$pid" 2>/dev
/null
; do
184 [ $
(( cnt
-= 1 )) -gt 0 ] ||
break
186 if kill -0 "$pid" 2>/dev
/null
; then
187 log_failure_msg
"Failed to stop $dmninst, pid $pid still running"
191 log_success_msg
"Stopped $dmninst"
198 local dmninst daemon inst pidfile pid fail
201 pidfile
="$V_PATH/$daemon${inst:+-$inst}.pid"
203 [ -r "$pidfile" ] ||
return 3
204 pid
="`cat \"$pidfile\"`"
205 [ -z "$pid" ] && return 1
206 kill -0 "$pid" 2>/dev
/null ||
return 1
213 if [ "$rv" -eq 0 ]; then
214 log_success_msg
"Status of $1: running"
216 log_failure_msg
"Status of $1: FAILED"
222 # all-daemon commands
227 for dmninst
in $daemons; do
228 daemon_start
"$dmninst"
235 daemon_list daemons disabled
236 [ "$1" = "--reallyall" ] && daemons
="$daemons $disabled"
239 for dmninst
in $daemons; do
240 reversed
="$dmninst $reversed"
243 for dmninst
in $reversed; do
244 daemon_stop
"$dmninst" &
257 for dmninst
in $daemons; do
258 print_status
"$dmninst" || fail
=1
269 [ -r "$oldcfg" ] ||
return 0
270 [ -s "$oldcfg" ] ||
return 0
271 grep -v '^[[:blank:]]*\(#\|$\)' "$oldcfg" > /dev
/null ||
return 0
273 log_warning_msg
"Reading deprecated $oldcfg. Please move its settings to $C_PATH/daemons and remove it."
275 # save off settings from daemons for the OR below
276 for dmn
in $DAEMONS; do eval "_new_$dmn=\${$dmn:-no}"; done
280 # OR together the daemon enabling options between config files
281 for dmn
in $DAEMONS; do eval "test \$_new_$dmn != no && $dmn=\$_new_$dmn; unset _new_$dmn"; done
284 [ -r "$C_PATH/daemons" ] ||
{
285 log_failure_msg
"cannot run $@: $C_PATH/daemons does not exist"
290 load_old_config
"$C_PATH/daemons.conf"
291 load_old_config
"/etc/default/frr"
292 load_old_config
"/etc/sysconfig/frr"
294 if { declare -p watchfrr_options
2>/dev
/null || true
; } |
grep -q '^declare \-a'; then
295 log_warning_msg
"watchfrr_options contains a bash array value." \
296 "The configured value is intentionally ignored since it is likely wrong." \
297 "Please remove or fix the setting."
298 unset watchfrr_options
302 # other defaults and dispatch
308 debug
"frrcommon_main" "$@"
313 if [ "$1" = "all" -o -z "$1" ]; then
325 start
) daemon_start
"$@";;
326 stop
) daemon_stop
"$@";;