/usr/bin/syncache-drb is in syncache 1.4-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | #!/usr/bin/ruby
#
# SynCache dRuby object cache server
# (originally written for Samizdat project)
#
# Copyright (c) 2002-2011 Dmitry Borodaenko <angdraug@debian.org>
#
# This program is free software.
# You can distribute/modify this program under the terms of
# the GNU General Public License version 3 or later.
#
# vim: et sw=2 sts=2 ts=8 tw=0
require 'getoptlong'
require 'etc'
require 'syslog'
require 'drb'
require 'syncache'
class SynCacheDRb
PNAME = 'syncache-drb'
def usage
puts %{
Usage: #{PNAME} [ options ] [ URI ]
Options:
URI
URI with druby: schema that DRb server binds to, default is
druby://*:9000
--help
display this message and quit
--ttl SECONDS
time-to-live value for cache entries, default is 24 hours
--size ENTRIES
maximum number of objects in cache, default is 10000
--flush-delay SECONDS
rate-limit flush operations: if less than that number of seconds
has passed since last flush, next flush will be delayed; default
is no rate limit
--user USER
Run as USER if started as root. Default is nobody.
--error-log ERROR_LOG_PATH
File to write errors to. Default is /dev/null. When run as root,
the file is chowned to USER:adm.
--debug
Enable debug mode. If an error log is specified with --error-log,
all messages will be sent there instead of syslog.
--pidfile PATH
Path to the pidfile. By default, pidfile is created under
/var/run/#{PNAME}/ when run as root, or under $TMPDIR
otherwise. Location should be writeable by USER.
--foreground
Do not daemonize, switch to a different user, create pidfile,
redirect output, or log to syslog.
}
exit
end
def set_options
opts = GetoptLong.new(
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
[ '--ttl', '-t', GetoptLong::REQUIRED_ARGUMENT ],
[ '--size', '-s', GetoptLong::REQUIRED_ARGUMENT ],
[ '--flush-delay', '-f', GetoptLong::REQUIRED_ARGUMENT ],
[ '--user', '-u', GetoptLong::REQUIRED_ARGUMENT ],
[ '--error-log', '-e', GetoptLong::REQUIRED_ARGUMENT ],
[ '--debug', '-d', GetoptLong::NO_ARGUMENT ],
[ '--pidfile', '-p', GetoptLong::REQUIRED_ARGUMENT ],
[ '--foreground', GetoptLong::NO_ARGUMENT ]
)
@uri = 'druby://*:9000'
@ttl = 24*60*60
@size = 10000
@flush_delay = nil
@user = 'nobody'
@error_log = '/dev/null'
@debug = false
@pidfile = (0 == Process.uid) ?
"/var/run/#{PNAME}/#{PNAME}.pid" :
File.join((ENV.has_key?('TMPDIR') ? ENV['TMPDIR'].dup.untaint : '/tmp'),
"#{PNAME}.pid")
@foreground = false
opts.each do |opt, arg|
case opt
when '--help'
usage
when '--ttl'
@ttl = arg.to_i
when '--size'
@size = arg.to_i
when '--flush-delay'
@flush_delay = arg.to_i
when '--user'
@user = arg.dup.untaint
when '--error-log'
@error_log = arg.dup.untaint
when '--debug'
@debug = true
when '--pidfile'
@pidfile = arg.dup.untaint
when '--foreground'
@foreground = true
end
end
@uri = ARGV[0].dup.untaint if ARGV[0]
@user = Etc.getpwnam(@user)
end
def log(message, level = :info)
if @log.respond_to? level
@log.send(level, message)
else
STDERR << 'syncache: ' + message + "\n"
STDERR.flush
end
end
def daemonize
$0 = PNAME
ENV.clear
exit if fork
Process.setsid
exit if fork
Dir.chdir '/'
File.umask 0022
STDIN.reopen '/dev/null'
STDOUT.reopen '/dev/null', 'a'
STDERR.reopen @error_log, 'a'
if 0 == Process.uid
if @error_log != '/dev/null'
File.chown(@user.uid, Etc.getgrnam('adm').gid, @error_log)
File.chmod(0640, @error_log)
end
# drop root priviledge
Process::Sys.setgid(@user.gid)
Process::Sys.setuid(@user.uid)
end
File.open(@pidfile, 'w') {|f| f.puts Process.pid }
end
def open_syslog
@log = Syslog.open PNAME
end
def ready
@cache = SynCache::Cache.new(@ttl, @size, @flush_delay) # initialize cache
@cache.debug = true if @debug
end
def trap_signals
shutdown = lambda do |sig|
Thread.new do
sleep 0.01
DRb.stop_service
end
end
Signal.trap('INT', shutdown)
Signal.trap('TERM', shutdown)
Signal.trap('HUP') do |sig| # kill -HUP to flush cache
Thread.new do
sleep 0.01
@cache.flush
log 'cache flushed'
end
end
end
def start_service
$SAFE = 1
DRb.start_service(@uri, @cache)
log 'started'
end
def wait_for_shutdown
DRb.thread.join
File.delete @pidfile unless @foreground
log 'shut down'
end
def run
set_options
unless @foreground
daemonize
open_syslog unless @debug and @error_log
end
begin
ready
trap_signals
start_service
wait_for_shutdown
rescue => error
log "#{error.class.to_s}: #{error.to_s}", :err
error.backtrace.each {|line| log(' ' + line, :err) }
raise
end
end
end
SynCacheDRb.new.run
|