
Linda Walsh wrote:
Per Jessen wrote:
At this point, I would say stick with systemd. It _does_ still have minor teething problems, but they are really mostly corner-cases. Occasionally migration incompatibilities appear where systemd no longer supports what one was used to in sysvinit (see for instance Carlos' spamd issue re inline comments).
How would you do something like the attached in systemd? Or another for 'rcscript status' gave a stop-like display... #!/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} is an *optional* # integer and is appended to the # start script name - to allow running # more than one instance -- I run 2 # a main one 'transmission, and a child # transmission1 # running multiple daemons allows finer # grain control of priorities ## note: "tmd" below, is my short-hand notation for "transmission-daemon" # When {XX} is noted, for XX>0, home dir directs to 'child{XX}' under # the real home directory # ### BEGIN INIT INFO # Provides: transmission # Required-Start: $network, $local_fs, # Should-Start: upnp $remote_fs named # Required-Stop: # Should-Stop: # 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)" use_group_access=1 if ((use_group_access)); then 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 fi # I set my user defaults here as I try to use the group for access # (doesn't actually work taht well because transmission-daemon # has a design flaw and set's it's umask to it's own arbitrary value # vs. allowing user to set it tmd_user=torrent # generic 'torrent' user to run torrents tmd_home="$(eval echo ~$tmd_user)" #they better have a home tmd_base_home="$tmd_home" tmd_group="$(groups torrent 2>/dev/null |cut -d\ -f3)" #and a real group tmd_child="" # note sudo is annoying to configure properly these days.. # best to sudo first then run this script: # (ex. "sudo /etc/rc.d/transmission start" 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=002 etc_loglevel=info #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/" #make sure we can write in piddir 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=5 # could use just "-c3" for lowest(idle) disk priority tmd_ionicep="-c2 -n7" # best effort; lowest in class tmd_existing_config=$tmd_home/settings.json # read the daemon's current config to get values...for defaults 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 opening config file: $!\n"; my $bash_hash = "declare -A $cfg=("; while (<$cfgh>) { chomp; m{^\s+ \" ([^"]+) \":\s+ \"? ([^"]+) \"? ,\s*$}x and do { my ($name, $val) = ($1, $2); $bash_hash .= qq{[$name]=\"$value\" }; }; } print "$bash_hash )\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" [[ ${Config[download-dir]:-} ]] && ddd="--download-dir ${Config[download-dir]}" [[ ${config[incomplete-dir]:-} ]] && icd="--incomplete-dir ${config[incomplete-dir]}" ### check for main data dirs being mounted [[ $ddd ]] dir1="${Config[download-dir]}" [[ $icd ]] dir2="${Config[download-dir]}" if [[ $dir1 && ! -d $dir1 || $dir2 && ! -d $dir2 ]]; then echo "Fatal error: Torrent data directories are not found" echo "this may mean a disk is not mounted: will not proceed" rc_fail 1 rc_status v exit 1 fi ## note -- if you don't want to configure one of these; just comment # it out - many of these will be set if it was able to # read the json file from transmission's home 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:-} " #open file limit for our machine ulimit -Hn16384 ulimit -Sn16384 ulimit -n 16384 ionice_bin=$(type -P ionice) # Check for existence of config files; # read system first # possibility of a system config... (I don't have one) test -r "${tmd_sys_config:-""}" && . "$tmd_sys_config" tmd_sys_config="/etc/sysconfig/transmission$tmd_child" # then read home-dir-config if present # I put my config in the 'tmd' daemon's home dir. # in an "etc" directory, in "rc-config" 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"}" #not sure how we could get this far w/o tmd_user not being set. 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 # Now read possible config options out of tmd user dir (I don't # use this as all my config vals are the defaults in this script! ;-) # but I DID use it to turn on options (debug and such) at times # in the past. # will look for a "environ" dir to read in "environment vars" # that you want to set for transmission (if any; if you # are doing development on it -- some debug options can be set in ENV # 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 # so note -- the tmd_secrets file can be anywhere -- it may # have been set in the tmd_environ's to anything, but it defaults # to a .secrets DIRECTORY in tmd_home # may be set by tmd_env # since this start script runs as root, these files probably don't # have to be readable by anyone # note -- I don't use a passwd on mine since it's interface is only # open on an internal network 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 # some util that lets you start scripts as a user/var and such... # 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 # SuSE's common run script env (only necessary for # defining "rc_xxxx" commands below that set status or exit #set # Reset status of this service rc_reset # set's startup value to 'ok' cd $tmd_home || { /bin/false rc_status -v # set bad status verbosely and leave 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