Dominique Leuenberger a.k.a. Dimstar wrote:
Quoting Linda Walsh
: I have at least 2 services I can think of off the top of my head that I run that suse doesn't provide run scripts for.
transmission-daemon and an ipmi-hw daemon.
Please check Factory again: there is a transmission-daemon package, which brings a systemd service file with it.
---- Hmm.... I see the file... I don't see it handling any configuration or what user it runs as... It references a config file, but the config file doesn't exist. Would it be useful / possible to use my startup script to start it? Mine reads the config file from the daemon and uses those arguments when restarting rather it allows hiding the password in separate location runs as it' own daemon and has support for running more than once instance -- (only tested once). I'll include it below and you can see why I might not want to give up the functionality. I haven't reviewed it for 'release', BUT i've been using it for 3 years... so it's likely in reasonable shape. There's some code to try to see if the user is in group 'torrent', and if so, allow them to run the script as a normal user... Has support for reading from sysconfig or ENV...as well as config files in torrent user dir (by instance if running multiple daemons)... The original is tab'ed @ 2 spaces, so I converted it to 2 spaces for below. to convert back to tabs in vim, set noet, just retab! 2, then the tabs will be set for the proper indentation and if you prefer 4 or 8, then reset your tabstop (ts=3/4/8...etc)... But the retab! with et/noet make it str8 forward to recover original tabbing. Anyway... this is a reasonably good example of a start/stop script...IMO..tried to make it as flexible as possible.... ---- #!/bin/bash # # /etc/rc.d/transmission.rc script by Astara at tlinx.org (c) 2010 # use, modify and derive from, as thou wilt. If you find this useful # that's great! If you want to mention me in credits, that a bonus! Enjoy! # Developed and tested on suse 11.2 - 12.2 # transmission[{XX}] [verb] [{XX}] -- where {XX} can be an an integer and # occur as part of filename or as a # parameter and indicates which instance # or copy to control # When {XX} is noted, for XX>0, home dir directs to 'child{XX}' under # the real home directory # ### BEGIN INIT INFO # Provides: tmd # Required-Start: $network, $local_fs, # Should-Start: upnp $remote_fs named # Required-Stop: # Should-Stop: et e Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Short-Description: transmission-daemon: a file transfer daemon # Description: transmission-daemon is a file transfer daemon utilizing # the 'bit-torrent' protocol. This allow for transferring # large amounts of data by sharing the network bandwith # among downloaders. Note -- to make effective use of # this client, it is necessary to allow incoming and # outgoing traffic through a firewall. # Only 1 port needs to be open and this can be defined # statically -- so you can manually add rules to your # firewall. The daemon will use upnp to talk to a # compliant firewall to ask it to open a port for it, # allowing for port randomization on startup, if that # is desired. Software upnp programs, like 'linux-igd' # are freely available by searching on the web, will # function as a upnp gateway and will manage connections # through a linux or other firewall. ### END INIT INFO # ## support code & functions Id="$(type -p id)" Sed="$(type -p sed)" Sudo="$(type -p sudo)" unset Groups typeset -Ax Groups function _idparse { # parse output of id: # uid=##(name) gid=##(name) groups=##(name)[,##(name)]... # Note, names may be 'absent' (in which case there are no parens). # grouplist is *comma* separated! -- but only on output of 'id'; # I don't "idnames" can start with a number... (we'll assume not) # if group has no name, put it's number in as it's name # else you wouldn't see you are in those groups while read id ; do [[ $id =~ .?id= ]] && continue; #skip over uid/gid entries id="${id/\(/ }" id="${id/\)/}" gid="${id%% *}" name="${id#$gid}" name=${name##\ } [[ -z $name ]] && name="$gid" Groups[$name]="$gid" done < <($Id|$Sed -r ' s/\) gid/\)\ngid/ ; s/\) groups/\)\ngroups/ ; s/\\/\\\\/g ; s/\),([0-9])/)\n\1/g ; s/\b([0-9]+),/\1\n/g ; s/groups=//') } _idparse ## populate Groups Hash tmd_user=torrent tmd_home="$(eval echo ~$tmd_user)" tmd_base_home="$tmd_home" tmd_group="$(groups torrent 2>/dev/null |cut -d\ -f3)" tmd_child="" if (($EUID != 0)) ; then if [[ -n ${Groups[$tmd_group]:-} ]]; then if [[ -z ${TRIED_ROOT:-} ]]; then export TRIED_ROOT="yes" exec sudo -E -g "$tmd_group" $0 "$@" fi fi echo "Need Root privs to successully run this script..." exit -1 fi unset TRIED_ROOT >&/dev/null || ((0)) #no longer needed #presumably user is root-priv'ed now. #parse command instance prog="$(basename "$0")" core="$(echo $prog |sed -r 's/^.*transmission/trm/ ; s/^.*trm[0]*([1-9][0-9]+)/trm$1/')" [[ ${core:0:3} == trm && ${#core} -gt 3 ]] && tmd_child="${core:3}" [[ $# -gt 1 && $2 =~ ^[0-9]+$ ]] && tmd_child="$2" tmd_child="${tmd_child##0}" [[ $tmd_child ]] && tmd_home="$tmd_home/child$tmd_child" tmd_umask=2 etc_loglevel=error #default logging level #unset tmd_use_proxy # default # don't use these by default if [[ ! ${use_proxy:-} =~ ^y ]]; then unset -v http_proxy unset -v ftp_proxy unset -v https_proxy fi if [[ -r ${tmd_log_level_file:-""} ]]; then nlvl=$(<"$tmd_log_level_file") if [[ $nlvl == info || $nlvl == debug || $nlvl == error || $nlvl == none ]] ; then etc_loglevel=$nlvl fi fi # use prefix 'tmd' = instead of full program/service name; its just too long tmd_bin="/usr/bin/transmission-daemon" tmd_piddir="/var/run/transmission/" if [[ ! -d $tmd_piddir ]]; then mkdir -m 6775 "$tmd_piddir" && chown $tmd_user.$tmd_group $tmd_piddir fi tmd_pidfile="$tmd_piddir/transmission-daemon$tmd_child.pid" tmd_logdir="/var/log/transmission" tmd_log="$tmd_logdir/daemon$tmd_child.log" tmd_output_log="$tmd_logdir/output$tmd_child.log" tmd_nice=-3 tmd_ionicep="-c2 -n7" # best effort; lowest in class tmd_existing_config=$tmd_home/settings.json function read_json_config { local cfg="${1:-}" local fl="${2:-}" typeset -A $cfg perl -wE ' use 5.12.0; $|=1; my $cfg=shift @ARGV; open (my $cfgh, "<", $ARGV[0]) or die "error w/file $!\n"; my $outs="declare -A $cfg=("; while (<$cfgh>) { chomp; m{^\s+\"([^"]+)\":\s+\"?([^"]+)\"?,\s*$} and do { my ($n, $v) = ($1, $2); $n =~ s/-/_/g; $outs .= qq{[$n]=\"$v\" }; }; } print "$outs )\n"; ' "$cfg" "$fl" } if [[ $# -ge 2 ]]; then eval $(read_json_config "$1" "$2") fi eval $(read_json_config Config "$tmd_home/settings.json") ################################################################ # 'default' tmd_a_rgs: # #[[ ${Config[blocklist_enabled]} =~ true ]] && blocklist="--blocklist" [[ -n "${Config[download_dir]}" ]] && ddd="--download-dir ${Config[download_dir]}" tmda_config_dir="--config-dir $tmd_home" tmda_dht="--dht" tmda_encryption="--encryption-tolerated" tmda_foreground="-f" tmda_incomplete_dir="--incomplete-dir $tmd_home/data/Downloading/transmission$tmd_child" tmda_local_peer_discovery="--lpd" tmda_logfile="--logfile $tmd_log" tmda_loglevel="--log-error" if [[ -z "$etc_loglevel" || $etc_loglevel == none ]] ; then tmda_logfile="--logfile /dev/null" else tmda_loglevel="--log-$etc_loglevel" fi tmda_pidfile="--pid-file $tmd_pidfile" tmda_portmap="--no-portmap" tmda_peer_port="${tmda_peer_port_number:+"--peerport $tmda_peer_port_number"}" tmda_port="${tmda_port_number:+"--port $tmda_port_number"}" tmda_rpc_allowed_access="--allowed 192.168.4.*,192.168.3.*,127.0.0.1" tmda_seedratio_glob="--no-global-seedratio" tmda_watchdir="--no-watch-dir" tmd_args=" ${tmda_blocklist:-} ${tmda_complete_dir:-} ${tmda_config_dir:-} ${tmda_dht:-} ${tmda_encryption:-} ${tmda_foreground:-} ${tmda_incomplete_dir:-} ${tmda_local_peer_discovery:-} ${tmda_logfile:-} ${tmda_loglevel:-} ${tmda_peerlimit_glob:-} ${tmda_peerlimit_per_torrent:-} ${tmda_peerport:-} ${tmda_port:-} ${tmda_pidfile:-} ${tmda_portmap:-} ${tmda_rpc_allowed_access:-} ${tmda_rpc_user:-} ${tmda_rpc_userpw:-} ${tmda_rpc_auth:-} ${tmda_seedratio_glob:-} ${tmda_watchdir:-} " ulimit -Hn16384 ulimit -Sn16384 ulimit -n 16384 ionice_bin=/usr/bin/ionice if [[ ! -e $ionice_bin ]]; then ionice_bin=$(which ionice) fi # Check for existence of config files; # read system first test -r "${tmd_sys_config:-""}" && . "$tmd_sys_config" tmd_sys_config="/etc/sysconfig/transmission$tmd_child" # then read home-dir-config if present tmd_home_config="$tmd_home/etc/rc-config" test -r "$tmd_home_config" && . "$tmd_home_config" tmd_etc="${tmd_etc:-"$tmd_home/etc"}" tmd_log_level_file="${tmd_log_level_file:-"$tmd_etc/log_level"}" if [[ -z ${tmd_user:-} ]]; then echo "tmd_user not set!" exit -1 fi if [[ -z ${tmd_group:-} ]]; then echo "User \"$tmd_user\" has no group -- (no /etc/passwd?)" exit -1 fi if [[ -z ${tmd_home:-} ]]; then echo "Configuration error: user \"$tmd_user\" has no home dir " exit -1 fi # read env options... tmd_env="${tmd_env:-"$tmd_home/environ"}" if [[ -d $tmd_env ]]; then if [[ ! -r $tmd_env || ! -x $tmd_env ]]; then echo "Environment directory $tmd_env exists, but isn't readable" echo "Environment variables will be ignored" else cd $tmd_env; readarray vars <<<$(find . -type f -name '[^.]*' -print|tr ) if ((${#vars[*]}>0)); then for var in "${vars[@]}" ; do echo "var=$var" export $var=$(<"$var") done cd - >/dev/null fi fi fi # may be set by tmd_env tmd_secrets="${tmd_secrets:-"$tmd_home/.secrets"}" tmd_usr_file="$tmd_secrets/.tmd_user" tmd_upw_file="$tmd_secrets/.tmd_userpw" if [[ -r $tmd_usr_file ]]; then tmda_rpc_user="$(<$tmd_usr_file)" fi tmda_rpc_user="${tmda_rpc_user:+"--username $tmda_rpc_user"}" if [[ -r $tmd_upw_file ]]; then tmda_rpc_userpw="$(<$tmd_upw_file)" fi tmda_rpc_userpw="${tmda_rpc_userpw:+"--password $tmda_rpc_userpw"}" if [[ -n ${tmda_rpc_user:-""} && -n ${tmda_rpc_userpw:-""} ]]; then tmda_rpc_auth="--auth" fi # non configurable vars go after here... #startproc stprc="/sbin/startproc" [[ ! -e $stprc ]] && stprc=$(which startproc) [[ ! -e $stprc ]] && { echo "Fatal: startproc not found" >&2; exit 1 ; } #startproc's arg list.... startproc_args=" -l $tmd_output_log -p $tmd_pidfile -u $tmd_user -g $tmd_group -n $tmd_nice" test -x $tmd_bin || { echo "$tmd_bin not installed"; if [ "$1" = "stop" ]; then exit 0; else exit 5; fi; } sp_args="$startproc_args" # Shell functions sourced from /etc/rc.status: # rc_check check and set local and overall rc status # rc_status check and set local and overall rc status # rc_status -v be verbose in local rc status and clear it afterwards # rc_status -v -r ditto and clear both the local and overall rc status # rc_status -s display "skipped" and exit with status 3 # rc_status -u display "unused" and exit with status 3 # rc_failed set local and overall rc status to failed # rc_failed <num> set local and overall rc status to <num> # rc_reset clear both the local and overall rc status # rc_exit exit appropriate to overall rc status # rc_active checks whether a service is activated by symlinks set +e +u # rc.status has buggy code . /etc/rc.status #set # Reset status of this service rc_reset cd $tmd_home || { /bin/false rc_status -v rc_exit } running=0 if [[ $1 != status ]]; then /sbin/checkproc -p $tmd_pidfile $tmd_bin running=$? if [[ $running == 0 ]]; then running=1 else running=0 fi fi case "$1" in start) if (($running)) ; then echo -n "Transmission already running... " else echo -n "Starting transmissiond " ## Start daemon with startproc(8). If thikks fails ## the return value is set appropriately by startproc. if [[ -n "$tr_umask" ]]; then umask $tr_umask fi all_args="$startproc_args $tmd_bin $tmd_args" if [[ -x $ionice_bin && -n "${tmd_ionicep:-}" ]]; then $ionice_bin $tmd_ionicep $stprc $all_args else $stprc $all_args fi fi # Remember status and be verbose rc_status -v ;; stop) if ((!$running)) ; then echo -n "Transmission is already stopped... " else echo -n "Shutting down transmissiond " ## Stop daemon with killproc(8) and if this fails ## killproc sets the return value according to LSB. /sbin/killproc -t 10 -p $tmd_pidfile -TERM $tmd_bin || { echo -n "Sending Kill..." /sbin/killproc -p $tmd_pidfile -t 1 -KILL $tmd_bin } fi # Remember status and be verbose rc_status -v ;; try-restart|condrestart) ## Do a restart only if the service was active before. ## Note: try-restart is now part of LSB (as of 1.9). ## RH has a similar command named condrestart. if test "$1" = "condrestart"; then echo -n "${attn} Use try-restart ${done}(LSB)${attn} " echo "rather than condrestart ${warn}(RH)${norm}" fi $0 status if test $? = 0; then $0 restart else rc_reset # Not running is not a failure. fi # Remember status and be quiet rc_status ;; restart) ## Stop the service and regardless of whether it was ## running or not, start it again. $0 stop $0 start # Remember status and be quiet rc_status ;; status) echo -n "Checking for service transmission-daemon${tmd_child} " ## Check status with checkproc(8), if<F5><F5> process is running ## checkproc will return with exit status 0. # Return value is slightly different for the status command: # 0 - service up and running # 1 - service dead, but /var/run/ pid file exists # 2 - service dead, but /var/lock/ lock file exists # 3 - service not running (unused) # 4 - service status unknown :-( # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) # NOTE: checkproc returns LSB compliant status values. /sbin/checkproc -p $tmd_pidfile $tmd_bin # NOTE: rc_status knows that we called this init script with # "status" option and adapts its messages accordingly. rc_status -v ;; probe) ## Optional: Probe for the necessity of a reload, print out the ## argument to this init script which is required for a reload. ## Note: probe is not (yet) part of LSB (as of 1.9) if [[ $tmd_sys_config -nt $tmd_pidfile || $tmd_home_config -nt $tmd_pidfile ]]; then echo reload fi ;; *) echo "Usage: $0 {start|stop|status|try-restart|restart|probe}" exit 1 ;; esac rc_exit # vim: ts=2 sw=2 syntax=sh -- To unsubscribe, e-mail: opensuse-factory+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-factory+owner@opensuse.org