Einfacher Zugriff auf rc.d Skripte

Kamikaze

Warrior of Sunlight
Teammitglied
Mir ging es auf die Nerven immer
Code:
# /usr/local/etc/rc.d/apache22.sh onestart
# /usr/local/etc/rc.d/mysql-server onestart
# /usr/local/etc/rc.d/010.pgsql.sh
zu tippen, wenn ich an meinem PHP-Code arbeiten will. Also habe ich mir in /root/bin unter dem Namen 'start' folgendes Skript angelegt.
Code:
#!/bin/sh

# Get a list of all startup script paths.
{
	# This path is obligatory.
	script_paths="/etc/rc.d"

	# Load default folders for local startup.
	eval $(grep "^local_startup=" /etc/defaults/rc.conf)
	eval $(grep "^rc_conf_files=" /etc/defaults/rc.conf)

	# Try to overwrite them with settings in /etc/rc.conf
	# this should normally fail silently. 
	eval $(grep "^local_startup=" $rc_conf_files 2> /dev/null)

	script_paths="$script_paths $local_startup"
}

# Use the script call as a command given to the selected startscript.
# Several commands can be realized with symlinks to this script,
# such as stop, status, onestart and so on.
command=$(echo $0 | grep -Eo "[^/]+$")

# Outputs a list of all services provided by the available startup scripts.
start_list() {
	# Grep for services over all startup scripts.
	# This looks a bit messy because it is not relying on a fixed amount
	# of spaces and tabs.
	for script_path in $script_paths; {
		grep -E "#[[:space:]]*PROVIDE:[[:space:]]*" $script_path/* | grep -Eo "[^:]+$" | grep -Eo "[^[:space:]]+"
	}
}

# Option triggers.
option_verbose=0

# Looks for the script that provides the service given as the first parameter
# and executes it. It returns the return value of the executed script or 1
# if no script that provides the requested service was found.
start_script() {
	# This is the name of the service to start.
	service=$1

	# Go through the list of script_paths and execute the first
	# script that provides the wanted service.
	for script_path in $script_paths; {
		# This breaks if a service is provided by more than 1 script
		# in the same folder.
		script=$(grep -El "#[[:space:]]*PROVIDE:[[:space:]]*$service[[:space:]]*$" $script_path/*)
		if [ "$script" != "" ]; then
			if [ $option_verbose -eq 1 ]; then
				echo "$service command:	$script $command"
			fi

			eval "$script $command"
			return $?
		fi
	}

	# No script offering the given service has been found.
	return 1
}

# Display help.
start_help() {
	echo "start ($command) v1.0.0
usage:	start [-v] [-n] [-p] [-s] [-h] [services]
description:
	This program was written to have easier access to init scripts in the
	rc.d folders. The parameter given to those scripts is its own name.
	Different parameters are realized by symlinking.
	The author uses the following links:
		stop status restart onestart onestop onestatus onerestart
options:
	--verbose
	-v	Be verbose after this parameter.
	--not-verbose
	-n	Do not be verbose after this parameter.
	--paths
	-p	Display the paths with init scripts.
	--services
	-s	Display the services provided by all init scripts.
	--help
	-h	Display this help.
services:
	A service is provided by an init script in an rc.d folder. Look for
	the PROVIDE keyword if you want to know the name of the service a
	script provides."
}

# Handle options.
start_options() {
	case $1 in
		"-v" | "--verbose") {
			option_verbose=1
			return 0
		};;
		"-n" | "--not-verbose" ) {
			option_verbose=0
			return 0
		};;
		"-p" | "--paths") {
			echo "$script_paths" | grep -Eo "[^[:space:]]+"
			return 0
		};;
		"-s" | "--services") {
			start_list
			return $?
		};;
		"-h" | "--help") {
			start_help
			return 0
		};;
		-? | --*) {
			echo "Unknown parameter \"$1\""
			return 0
		};;
		-*) {
			# Split parameters.
			parameters=$(echo $1 | grep -Eo "[[:alnum:]]" | sed "s|^|-|g")
			for parameter in $parameters; {
				start_options $parameter
			}
			return 0
		};;
	esac

	# The given parameter is not an option.
	return 1
}

# Run the requested services.
return_value=0
for parameter; {
	if ! start_options $parameter ; then
		start_script $parameter
		return_value=$?
		if [ $option_verbose -eq 1 ]; then
			echo "$service returned:	$return_value"
		fi
	fi
}

# Exit with the return value of the last init script.
exit $return_value

Das Skript erzeugt den Parameter der den rc.d Skripten übergeben wird aus seinem eigenen Namen, also habe ich noch ein paar links angelegt.
Code:
# cd /root/bin
# ln -s start stop
# ln -s start status
# ln -s start restart
# ln -s start onestart
# ln -s start onestop
# ln -s start onestatus
# ln -s start onerestart

Jetzt hat der Aufruf
Code:
# onestart apache22 mysql postgresql
den gleichen Effekt wie der Dreizeiler.

Das Skript sollte hoffentlich auf allen BSDs funktionieren die das rc.d System von NetBSD verwenden. Vorrausgestzt die Implementierungen von grep sind gleich und die Pfade '/etc/rc.d', '/etc/rc.conf' und '/etc/defaults/rc.conf' sind gleich. Gebastelt wurde das ganze auf FreeBSD 6-stable.

Wenn man den Parameter "-s" angibt gibt das Skript einer Liste aller Dienste die es finden kann aus. Das beinhaltet auch die in '/etc/rc.d', also ist die Liste recht lang. Ansonsten gibt der Parameter "-h" eine kurze Hilfe.
 
Zuletzt bearbeitet:
kleine anmerkung: wieso greppst du in rc.conf bzw defaults/rc.conf rum? "source" doch einfach rc.conf, welches von sich aus schon defaults/rc.conf nachlaedt und benutze die variable ganz normal, die dich interessiert.
 
Einfach, weil da ein Haufen Zeug drin steht den ich sowieso nicht brauche. Unter freebsd lädt übrigens die defaults/rc.conf die anderen nach.
 
Gute Idee. Ich würde statt der vielen Links (die potentiell mit anderen Dingen kollidieren könnten) das script 'rc.d' nennen und die Aktion als ersten Parameter übergeben.

Was hält's Du von folgender Erweiterung?

Code:
...
command=$(echo $0 | grep -Eo "[^/]+$")

# usage-style 'rc.d <action> <services> ....'
if [ "$command" = "rc.d" ] ; then
  command=$1; shift
fi
...
 
Würde ich inzwischen auch so machen, aber dann müsste ich wegen der Kompatibiltät mehrere Ports pflegen.
 
Deswegen habe ich den Vorschlag ja so formuliert, daß er "kompatibel" mit dem ursprünglichen Vorschlag ist.

Wenn man das script tatsächlich (/usr/local/bin/) rc.d nennt, kann man immer noch die genannten symbolische links (und dann natürlich zusätzlich noch einen für 'start') anlegen.

BTW: Ich glaube, bei einigen Linuxen ist "rc-invoke" ein etablierter Name für exakt diese Funktionalität.
 
Hi,

ich habe das Problem einfach mit dem Shell-Handwerkszeug gelößt,
wenn auch nicht ganz so komfortabel.

Da ich die "bash" der "csh" vorziehe habe ich in die ".profile" Datei im Heimatverzeichnis
des betreffenden Nutzers für solche Dinge einen Alias eingerichtet, um wichtige
Kommandos immer schnell griffbereit zu haben.

Code:
alias    e="/usr/local/etc/rc.d/samba restart"
um das Alias zu aktiveren brauche ich nur "e" (ENTER) eintippen,
und siehe da,"smbd stopped .. smbd started", natürlich ist es auch
möglich Aliases mit mehr als einem Buchstaben zu definieren.
 
Zurück
Oben