Hi, I have a Python software called "py_program". It runs as daemon in Linu=
x=20
so doing a "ps" I get:
root 6541 /usr/bin/python /home/ibc/py_program
However in /proc/6541/status I read:
Name: py_program
This is good because this means that in Debian it can be stopped with the=20
command:
start-stop-daemon --stop --name py_program
Anyhow the proces name is "python" still rather than "py_program":
~# netstat -putan | grep 6541
6541/python
and I cannot kill the process with "killall py_program".
Well, I'm coding a server "rb_program" in Ruby (a HTTP server built with Ra=
ck)=20
and the behavior is different:
root 5412 ruby1.9 /home/ibc/rb_program
In /proc/5412/status:
Name: ruby1.9
So I cannot use "start-stop-daemon --stop --name rb_program" because it wou=
ld=20
find no process names "rb_program"
(and of course I cannot use "--name ruby1.9" as I would stop any ruby progr=
am=20
running in the host).
So, is there some way to force the process to appear as "rb_program" in=20
/proc/PID/status?
Thanks a lot.
=20
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
ibc (607)
|
12/11/2009 10:34:04 PM |
|
El Viernes, 11 de Diciembre de 2009, I=C3=B1aki Baz Castillo escribi=C3=B3:
> So, is there some way to force the process to appear as "rb_program" in=20
> /proc/PID/status?
I forgot to say that a dirty workaround is creating a link to ruby binary =
=20
called "rb_program".
Of course is really dirty :)
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/11/2009 11:08:02 PM
|
|
On Friday 11 December 2009 04:34:04 pm I=C3=B1aki Baz Castillo wrote:
> This is good because this means that in Debian it can be stopped with the
> command:
>=20
> start-stop-daemon --stop --name py_program
[snip]
> So I cannot use "start-stop-daemon --stop --name rb_program" because it
> would find no process names "rb_program"
This is probably not a good idea in the first place -- it means you can't h=
ave=20
separate copies of the program running, and start/stop them independently, =
to=20
say nothing of the possibility that some other program might share the same=
=20
name.
Since you're using start-stop-daemon anyway, why don't you make a pidfile?
start-stop-daemon --start --startas /home/ibc/rb_program --make-pidfile --
pidfile /var/run/rb_program.pid --background
If your program is backgrounding itself already, configure it to create its=
=20
own pidfile -- shouldn't be too hard. Then you can do this instead:
start-stop-daemon --stop --pidfile /var/run/rb_program.pid
> So, is there some way to force the process to appear as "rb_program" in
> /proc/PID/status?
I'd like to know that, too, because it'd be useful for things like killall=
=20
when things get out of hand. But even if there was, this is still the wrong=
=20
approach -- your start-stop-daemon command is sort of equivalent to killall=
,=20
which is a really blunt instrument.
|
|
0
|
|
|
|
Reply
|
David
|
12/11/2009 11:11:06 PM
|
|
El S=C3=A1bado, 12 de Diciembre de 2009, David Masover escribi=C3=B3:
> > So I cannot use "start-stop-daemon --stop --name rb_program" because it
> > would find no process names "rb_program"
>=20
> This is probably not a good idea in the first place -- it means you can't
> have separate copies of the program running, and start/stop them
> independently, to say nothing of the possibility that some other program
> might share the same name.
>=20
> Since you're using start-stop-daemon anyway, why don't you make a pidfile?
>=20
> start-stop-daemon --start --startas /home/ibc/rb_program --make-pidfile --
> pidfile /var/run/rb_program.pid --background
>=20
> If your program is backgrounding itself already, configure it to create i=
ts
> own pidfile -- shouldn't be too hard. Then you can do this instead:
>=20
> start-stop-daemon --stop --pidfile /var/run/rb_program.pid
Yes, in fact I use it now: my Ruby server creates a pidfile.
The good point of using:
start-stop-daemon --stop --pidfile /var/run/rb_program.pid --name rb_prog=
ram
is that it would stop the process just if it's called "rb_program" and its =
pid=20
matches the value of /var/run/rb_program.pid, so you cannot kill any other=
=20
process using that pid by accident (it could occur if your program didn't=20
delete the pidfile and a new process has taken same pid value).
> > So, is there some way to force the process to appear as "rb_program" in
> > /proc/PID/status?
>=20
> I'd like to know that, too, because it'd be useful for things like killall
> when things get out of hand. But even if there was, this is still the wro=
ng
> approach -- your start-stop-daemon command is sort of equivalent to
> killall, which is a really blunt instrument.
>=20
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/11/2009 11:33:06 PM
|
|
On Friday 11 December 2009 05:33:06 pm I=C3=B1aki Baz Castillo wrote:
> The good point of using:
>=20
> start-stop-daemon --stop --pidfile /var/run/rb_program.pid --name
> rb_program
>=20
> is that it would stop the process just if it's called "rb_program" and its
> pid matches the value of /var/run/rb_program.pid, so you cannot kill any
> other process using that pid by accident (it could occur if your program
> didn't delete the pidfile and a new process has taken same pid value).
That's a good point -- though I would guess that in theory, it shouldn't be=
=20
possible for a program to die in such a way that it wouldn't be able to del=
ete=20
that file. The only thing that would make sense is a reboot, and on my syst=
em,=20
/var/run is a tmpfs (only exists in RAM/swap), so it's not stored anywhere=
=20
that would survive a reboot.
I can think of a few other possibilities, like checking directly (with fuse=
r,=20
for example) which process is controlling the resource your daemon is=20
associated with, or even talking to the old daemon over a socket, or some s=
ort=20
of formal IPC like dbus.
I'm not sure about Debian, but on Ubuntu, the upstart system might also be=
=20
worth looking into.
I did find a solution, though:
#!/usr/bin/env ruby
doesn't work. However:
#!/usr/bin/ruby1.9.1
produces a process which responds both to killall and to 'start-stop-daemon=
--
stop --name'. But hardcoding the location of the Ruby interpreter is=20
antisocial, especially when there are so many of them. The whole point of e=
nv=20
is that I can always override PATH and point to a different Ruby interprete=
r,=20
to easily switch between 1.8, 1.9, JRuby, Rubinius, etc.
I thought I'd found a workaround, and I've been getting messy with C trying=
to=20
figure out how to replace env with a more appropriate program, but I'm not=
=20
sure how to change the program name at all. That is, this isn't a Ruby issu=
e,=20
it's a Linux/Unix issue. The best I could figure out was this:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[]) {
if (argc =3D=3D 1) {
fprintf(stderr, "Usage: %s PROGRAM ARGUMENTS\n", argv[0]);
return 1;
}
char * filename =3D argv[1];
argv[1] =3D "foo";
execvp(filename, argv+1);
char * outstr =3D malloc(strlen(argv[0]) + strlen(argv[1]) + 2);
sprintf(outstr, "%s: %s", argv[0], argv[1]);
perror(outstr);
return errno;
}
Compile that, then change the Ruby script to be:
#!/path/to/that/binary ruby
The same should work for Python.
Except it doesn't.
It does indeed change the program name in /proc/self/cmdline -- it becomes=
=20
'foo /name/of/my/program.rb'. And killall and start-stop-daemon both seem t=
o=20
work, here, but only when I give them "ruby" as the name of the program to=
=20
kill.
Notice, also, I'm explicitly setting 'foo' as the program name. If this=20
worked, I'd detect that dynamically -- but it doesn't.
At this point, I'm about ready to write a script that would copy your scrip=
t=20
(or create a wrapper for your script) and change the shebang to match `whic=
h=20
ruby` at the point of invocation, but that wouldn't work either -- that wil=
l=20
fool the program name in /proc, but it won't fool your program -- there's $=
0=20
and probably a dozen other things I haven't thought of to tell it that it's=
=20
being loaded by a separate script.
I don't really know what else to try. /proc/self/exe is no help; that point=
s=20
to the Ruby binary no matter what. You might write your own script that gre=
ps=20
through /proc/*/cmdline, but I don't see a way to fool start-stop-daemon=20
without changing to #!/usr/bin/ruby1.9.1.
|
|
0
|
|
|
|
Reply
|
David
|
12/12/2009 1:21:10 AM
|
|
El S=C3=A1bado, 12 de Diciembre de 2009, David Masover escribi=C3=B3:
> On Friday 11 December 2009 05:33:06 pm I=C3=B1aki Baz Castillo wrote:
> > The good point of using:
> >
> > start-stop-daemon --stop --pidfile /var/run/rb_program.pid --name
> > rb_program
> >
> > is that it would stop the process just if it's called "rb_program" and
> > its pid matches the value of /var/run/rb_program.pid, so you cannot kill
> > any other process using that pid by accident (it could occur if your
> > program didn't delete the pidfile and a new process has taken same pid
> > value).
>=20
> That's a good point -- though I would guess that in theory, it shouldn't =
be
> possible for a program to die in such a way that it wouldn't be able to
> delete that file. The only thing that would make sense is a reboot, and =
on
> my system, /var/run is a tmpfs (only exists in RAM/swap), so it's not
> stored anywhere that would survive a reboot.
Well, usually daemons are coded to deelte the pidfile upon receipt of a SIG=
INT=20
signal (or some others). But if the daemon is killed with "kill -9 PID" the=
n=20
it terminates inmediately without deleting the piddile.
In the case of a crash or segmentfault the daemon wouldn't delete the pidfi=
le=20
again.
I've coded my Debian init script "start" action so it deletes the existing=
=20
"pidfile" if it exists (it shouldn't).
> I can think of a few other possibilities, like checking directly (with
> fuser, for example) which process is controlling the resource your daemon
> is associated with, or even talking to the old daemon over a socket, or
> some sort of formal IPC like dbus.
Sounds interesting, but perhaps a bit complex. I think I don't need so much=
as=20
there will be an unique instance of the ruby program running in the server.
> I did find a solution, though:
>=20
> #!/usr/bin/env ruby
>=20
> doesn't work. However:
>=20
> #!/usr/bin/ruby1.9.1
>=20
> produces a process which responds both to killall and to 'start-stop-daem=
on
> -- stop --name'.
Great! this is the point. I've checked the daemon in python and it uses=20
"/usr/bin/python" rather than "/usr/bin/env python".
> But hardcoding the location of the Ruby interpreter is
> antisocial, especially when there are so many of them. The whole point of
> env is that I can always override PATH and point to a different Ruby
> interpreter, to easily switch between 1.8, 1.9, JRuby, Rubinius, etc.
Yes, and when dealing with compiled sources rather than linux distribution=
=20
specific packages we could have ruby1.9 binay in /usr/local/bin/, /opt/bin/=
=2E..
I agree 100%. I wouldn't like to hardcode the ruby location.
=09
=20
> I thought I'd found a workaround, and I've been getting messy with C tryi=
ng
> to figure out how to replace env with a more appropriate program, but I'm
> not sure how to change the program name at all. That is, this isn't a Ru=
by
> issue, it's a Linux/Unix issue. The best I could figure out was this:
>=20
>=20
> #include <unistd.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <errno.h>
>=20
> int main(int argc, char *argv[]) {
> if (argc =3D=3D 1) {
> fprintf(stderr, "Usage: %s PROGRAM ARGUMENTS\n", argv[0]);
> return 1;
> }
>=20
> char * filename =3D argv[1];
> argv[1] =3D "foo";
>=20
> execvp(filename, argv+1);
>=20
> char * outstr =3D malloc(strlen(argv[0]) + strlen(argv[1]) + 2);
> sprintf(outstr, "%s: %s", argv[0], argv[1]);
> perror(outstr);
> return errno;
> }
>=20
>=20
> Compile that, then change the Ruby script to be:
>=20
> #!/path/to/that/binary ruby
>=20
> The same should work for Python.
>=20
> Except it doesn't.
>=20
> It does indeed change the program name in /proc/self/cmdline -- it becomes
> 'foo /name/of/my/program.rb'. And killall and start-stop-daemon both seem
> to work, here, but only when I give them "ruby" as the name of the progr=
am
> to kill.
>=20
> Notice, also, I'm explicitly setting 'foo' as the program name. If this
> worked, I'd detect that dynamically -- but it doesn't.
>=20
> At this point, I'm about ready to write a script that would copy your
> script (or create a wrapper for your script) and change the shebang to
> match `which ruby` at the point of invocation, but that wouldn't work
> either -- that will fool the program name in /proc, but it won't fool yo=
ur
> program -- there's $0 and probably a dozen other things I haven't thought
> of to tell it that it's being loaded by a separate script.
>=20
> I don't really know what else to try. /proc/self/exe is no help; that
> points to the Ruby binary no matter what. You might write your own script
> that greps through /proc/*/cmdline, but I don't see a way to fool
> start-stop-daemon without changing to #!/usr/bin/ruby1.9.1.
Thanks a lot for all your suggestions, it's a really interesting subject.
However I would prefer to keep the code as simple as possible. The only I=20
wanted was the possibility of kill my program using "killall rb_program".
To summarize this is possible in these cases:
a) Hardcoding the ruby location (avoiding using "env").
Not user-friendly.
b) Creating a link "rb_program" to ruby interpreter and invoke my program w=
ith=20
"rb_program /PATH_TO_rb_program.rb".
Not very beauty :)
c) Replacing env with your above suggestion.
It involves compiling a C program, it could break something in a not pure=20
Linux environment...
Well, I've learnt *a lot* in this thread but at this point I think is bette=
r=20
just to leave the code as it is.
Really thanks a lot.
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/12/2009 9:53:06 AM
|
|
Iñaki Baz Castillo wrote:
> So, is there some way to force the process to appear as "rb_program" in
> /proc/PID/status?
Have you tried
$0 = 'rb_program'
?
You may find there's a problem if your program name is longer than some
hard-coded limit. There is a workaround at
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/336743
At the top of your program put:
$progname = $0
alias $PROGRAM_NAME $0
alias $0 $progname
trace_var(:$0) {|val| $PROGRAM_NAME = val} # update for ps
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
Brian
|
12/12/2009 12:58:02 PM
|
|
Brian Candler wrote:
> Iñaki Baz Castillo wrote:
>> So, is there some way to force the process to appear as "rb_program" in
>> /proc/PID/status?
>
> Have you tried
>
> $0 = 'rb_program'
>
> ?
... or I can't remember the details, but perhaps you needed
$0.replace('rb_program'), but that doesn't work for newer versions of
Ruby where $0 is a frozen string, hence the required special code:
> $progname = $0
> alias $PROGRAM_NAME $0
> alias $0 $progname
> trace_var(:$0) {|val| $PROGRAM_NAME = val} # update for ps
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
Brian
|
12/12/2009 12:59:25 PM
|
|
El S=C3=A1bado, 12 de Diciembre de 2009, Brian Candler escribi=C3=B3:
> Brian Candler wrote:
> > I=C3=B1aki Baz Castillo wrote:
> >> So, is there some way to force the process to appear as "rb_program" in
> >> /proc/PID/status?
> >
> > Have you tried
> >
> > $0 =3D 'rb_program'
> >
> > ?
>=20
> ... or I can't remember the details, but perhaps you needed
> $0.replace('rb_program'), but that doesn't work for newer versions of
>=20
> Ruby where $0 is a frozen string, hence the required special code:
> > $progname =3D $0
> > alias $PROGRAM_NAME $0
> > alias $0 $progname
> > trace_var(:$0) {|val| $PROGRAM_NAME =3D val} # update for ps
Thanks a lot, it sounds really interesting.
However all the above works for me just by adding at the top:
$0 =3D "rb_program"
or:
$PROGRAM_NAME =3D "rb_program"=20
With it when I do a "ps" I see "rb_program" which is great.
However in /proc/PID/status I still have the same described issues: "Name:=
=20
ruby1.9", so I cannot do "killall rb_program".
This can be solved by using:
#!/usr/local/bin/ruby1.9
rather than:
#!/usr/bin/env ruby1.9
but of course hardcoding the location of ruby is not very good approach=20
(specially when you want your code to run on any Linux system).
Thanks a lot.
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/12/2009 1:49:46 PM
|
|
El S=C3=A1bado, 12 de Diciembre de 2009, I=C3=B1aki Baz Castillo escribi=C3=
=B3:
> However in /proc/PID/status I still have the same described issues: "Name:
> ruby1.9", so I cannot do "killall rb_program".
It seems to be more a "killall" issue since "pidof rb_program" works while=
=20
"killall rb_program" not.
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/12/2009 1:53:13 PM
|
|
El S=C3=A1bado, 12 de Diciembre de 2009, I=C3=B1aki Baz Castillo escribi=C3=
=B3:
> El S=C3=A1bado, 12 de Diciembre de 2009, I=C3=B1aki Baz Castillo escribi=
=C3=B3:
> > However in /proc/PID/status I still have the same described issues:
> > "Name: ruby1.9", so I cannot do "killall rb_program".
>=20
> It seems to be more a "killall" issue since "pidof rb_program" works while
> "killall rb_program" not.
>=20
I read in http://psmisc.sourceforge.net/changelog.html:
=2D---------
Changes from version 12 to 13 (16-APR-1997)
killall: now lists PIDs if invoked as "pidof" (proposed by Peter Daum)=20
=2D--------
This, if I do "killall rb_" and pres TAB (I've autocompletion) I get "killa=
ll=20
rb_program" but it doesn't work, it doesn't kill the process.
However if I do "pidof rb_program" I get its pid.
Strange... I'll report a bug in psmisc.
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/12/2009 2:19:00 PM
|
|
On 12.12.2009 10:53, I=F1aki Baz Castillo wrote:
> El S=E1bado, 12 de Diciembre de 2009, David Masover escribi=F3:
>> On Friday 11 December 2009 05:33:06 pm I=F1aki Baz Castillo wrote:
>>> The good point of using:
>>>
>>> start-stop-daemon --stop --pidfile /var/run/rb_program.pid --name
>>> rb_program
>>>
>>> is that it would stop the process just if it's called "rb_program" an=
d
>>> its pid matches the value of /var/run/rb_program.pid, so you cannot k=
ill
>>> any other process using that pid by accident (it could occur if your
>>> program didn't delete the pidfile and a new process has taken same pi=
d
>>> value).
>> That's a good point -- though I would guess that in theory, it shouldn=
't be
>> possible for a program to die in such a way that it wouldn't be able t=
o
>> delete that file. The only thing that would make sense is a reboot, a=
nd on
>> my system, /var/run is a tmpfs (only exists in RAM/swap), so it's not=
>> stored anywhere that would survive a reboot.
>=20
> Well, usually daemons are coded to deelte the pidfile upon receipt of a=
SIGINT=20
> signal (or some others). But if the daemon is killed with "kill -9 PID"=
then=20
> it terminates inmediately without deleting the piddile.
>=20
> In the case of a crash or segmentfault the daemon wouldn't delete the p=
idfile=20
> again.
>=20
> I've coded my Debian init script "start" action so it deletes the exist=
ing=20
> "pidfile" if it exists (it shouldn't).
You can make deletion conditionally depending on the presence of the=20
process (kill 0). This is what I would do:
VAR=3D'/var/run'
pid_file =3D File.join(VAR, File.basename($0) + '.pid')
begin
old_pid =3D File.read(pid_file).to_i
Process.kill 0, old_pid
$stderr.puts "ERROR: already running with PID #{old_pid}"
exit 1
rescue Errno::ENOENT
# no pid file
rescue Errno::ESRCH
# process not running
$stderr.puts 'WARNING: stale pid file'
end
# open file with EXCL in order to catch race conditions where two
# processes were started almost at the same time and both thought
# they would be a new instance. Uncomment sleep to simulate:
# sleep 2
File.open(pid_file, File::EXCL | File::WRONLY | File::CREAT) {|io|=20
io.write($$)}
trap(0) {File.delete pid_file}
puts "OK, here we go."
# just for testing purposes:
File.read(pid_file).to_i =3D=3D $$ or raise "What went wrong?"
sleep 10
puts "Finished"
> Thanks a lot for all your suggestions, it's a really interesting subjec=
t.
> However I would prefer to keep the code as simple as possible. The only=
I=20
> wanted was the possibility of kill my program using "killall rb_program=
".
Why does it have to be "killall"? What about providing a command line=20
option "-k" or "--kill" for killing (e.g. as ssh-agent does)? You could =
integrate that pretty easily with the PID handling code above.
> To summarize this is possible in these cases:
>=20
> a) Hardcoding the ruby location (avoiding using "env").
> Not user-friendly.
I personally do not find it too unfriendly to place the interpreter name =
with an absolute path in the script. This has also greater safety and=20
robustness: the one installing the program and ruby interpreter (some=20
person with administrative permissions) is likely the same and can=20
ensure location is set properly. Relying on users' environments is more =
fragile IMHO.
> b) Creating a link "rb_program" to ruby interpreter and invoke my progr=
am with=20
> "rb_program /PATH_TO_rb_program.rb".
> Not very beauty :)
>=20
> c) Replacing env with your above suggestion.
> It involves compiling a C program, it could break something in a not pu=
re=20
> Linux environment...
>=20
> Well, I've learnt *a lot* in this thread but at this point I think is b=
etter=20
> just to leave the code as it is.
> Really thanks a lot.
Well, it's your choice.
Kind regards
robert
--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
|
|
0
|
|
|
|
Reply
|
Robert
|
12/12/2009 4:24:00 PM
|
|
El S=E1bado, 12 de Diciembre de 2009, Robert Klemme escribi=F3:
> On 12.12.2009 10:53, I=F1aki Baz Castillo wrote:
> > El S=E1bado, 12 de Diciembre de 2009, David Masover escribi=F3:
> >> On Friday 11 December 2009 05:33:06 pm I=F1aki Baz Castillo wrote:
> >>> The good point of using:
> >>>
> >>> start-stop-daemon --stop --pidfile /var/run/rb_program.pid --name
> >>> rb_program
> >>>
> >>> is that it would stop the process just if it's called "rb_program" and
> >>> its pid matches the value of /var/run/rb_program.pid, so you cannot
> >>> kill any other process using that pid by accident (it could occur if
> >>> your program didn't delete the pidfile and a new process has taken sa=
me
> >>> pid value).
> >>
> >> That's a good point -- though I would guess that in theory, it shouldn=
't
> >> be possible for a program to die in such a way that it wouldn't be able
> >> to delete that file. The only thing that would make sense is a reboot,
> >> and on my system, /var/run is a tmpfs (only exists in RAM/swap), so it=
's
> >> not stored anywhere that would survive a reboot.
> >
> > Well, usually daemons are coded to deelte the pidfile upon receipt of a
> > SIGINT signal (or some others). But if the daemon is killed with "kill =
=2D9
> > PID" then it terminates inmediately without deleting the piddile.
> >
> > In the case of a crash or segmentfault the daemon wouldn't delete the
> > pidfile again.
> >
> > I've coded my Debian init script "start" action so it deletes the
> > existing "pidfile" if it exists (it shouldn't).
>=20
> You can make deletion conditionally depending on the presence of the
> process (kill 0). This is what I would do:
>=20
> VAR=3D'/var/run'
>=20
> pid_file =3D File.join(VAR, File.basename($0) + '.pid')
>=20
> begin
> old_pid =3D File.read(pid_file).to_i
> Process.kill 0, old_pid
> $stderr.puts "ERROR: already running with PID #{old_pid}"
> exit 1
> rescue Errno::ENOENT
> # no pid file
> rescue Errno::ESRCH
> # process not running
> $stderr.puts 'WARNING: stale pid file'
> end
>=20
> # open file with EXCL in order to catch race conditions where two
> # processes were started almost at the same time and both thought
> # they would be a new instance. Uncomment sleep to simulate:
> # sleep 2
> File.open(pid_file, File::EXCL | File::WRONLY | File::CREAT) {|io|
> io.write($$)}
> trap(0) {File.delete pid_file}
>=20
> puts "OK, here we go."
>=20
> # just for testing purposes:
> File.read(pid_file).to_i =3D=3D $$ or raise "What went wrong?"
>=20
> sleep 10
>=20
> puts "Finished"
>=20
> > Thanks a lot for all your suggestions, it's a really interesting subjec=
t.
> > However I would prefer to keep the code as simple as possible. The only=
I
> > wanted was the possibility of kill my program using "killall rb_program=
".
>=20
> Why does it have to be "killall"? What about providing a command line
> option "-k" or "--kill" for killing (e.g. as ssh-agent does)? You could
> integrate that pretty easily with the PID handling code above.
>=20
> > To summarize this is possible in these cases:
> >
> > a) Hardcoding the ruby location (avoiding using "env").
> > Not user-friendly.
>=20
> I personally do not find it too unfriendly to place the interpreter name
> with an absolute path in the script. This has also greater safety and
> robustness: the one installing the program and ruby interpreter (some
> person with administrative permissions) is likely the same and can
> ensure location is set properly. Relying on users' environments is more
> fragile IMHO.
>=20
> > b) Creating a link "rb_program" to ruby interpreter and invoke my progr=
am
> > with "rb_program /PATH_TO_rb_program.rb".
> > Not very beauty :)
> >
> > c) Replacing env with your above suggestion.
> > It involves compiling a C program, it could break something in a not pu=
re
> > Linux environment...
> >
> > Well, I've learnt *a lot* in this thread but at this point I think is
> > better just to leave the code as it is.
> > Really thanks a lot.
>=20
> Well, it's your choice.
Thanks a lot!
=2D-=20
I=F1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
iso
|
12/12/2009 6:09:38 PM
|
|
On Saturday 12 December 2009 03:53:06 am I=C3=B1aki Baz Castillo wrote:
> Well, usually daemons are coded to deelte the pidfile upon receipt of a
> SIGINT signal (or some others). But if the daemon is killed with "kill -9
> PID" then it terminates inmediately without deleting the piddile.
True. I tried (and failed) to find an example of this working. However, a=20
separate process can watch your process and clean up after it however it di=
es.=20
I think this is the principle behind letting init handle it -- take "upstar=
t".
> In the case of a crash or segmentfault the daemon wouldn't delete the
> pidfile again.
If the crash raises an exception, you can catch that. Segmentation faults=20
trigger SIGSEGV, which you can trap. I suspect you'd have a chance to at le=
ast=20
fire that unlink call with any death except a 'kill -9'.
> > I can think of a few other possibilities, like checking directly (with
> > fuser, for example) which process is controlling the resource your
> > daemon is associated with, or even talking to the old daemon over a
> > socket, or some sort of formal IPC like dbus.
>=20
> Sounds interesting, but perhaps a bit complex. I think I don't need so mu=
ch
> as there will be an unique instance of the ruby program running in the
> server.
Yes, probably too complex to do for a specific program. However, it might b=
e=20
worth wrapping into a library, if there isn't already one designed for this.
> Thanks a lot for all your suggestions, it's a really interesting subject.
> However I would prefer to keep the code as simple as possible. The only I
> wanted was the possibility of kill my program using "killall rb_program".
>=20
> To summarize this is possible in these cases:
>=20
> a) Hardcoding the ruby location (avoiding using "env").
> Not user-friendly.
However, if you distribute your app as a gem, this problem actually goes aw=
ay.=20
Here's the top of gems/rake-0.8.7/bin/rake:
#!/usr/bin/env ruby
#--
# Copyright (c) 2003, 2004, 2005, 2006, 2007 Jim Weirich
=2E..
Here's what it actually installs into your PATH:
#!/usr/bin/ruby1.9.1
#
# This file was generated by RubyGems.
#
# The application 'rake' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version =3D ">=3D 0"
if ARGV.first =3D~ /^_(.*)_$/ and Gem::Version.correct? $1 then
version =3D $1
ARGV.shift
end
gem 'rake', version
load Gem.bin_path('rake', 'rake', version)
So, that gives you the best of both worlds -- it's actually somewhat like o=
ne=20
of the crazier solutions I suggested.
> b) Creating a link "rb_program" to ruby interpreter and invoke my program
> with "rb_program /PATH_TO_rb_program.rb".
> Not very beauty :)
>=20
> c) Replacing env with your above suggestion.
Except (c) doesn't work. I thought it would work, and I posted it to the li=
st=20
in case I was close enough for someone to pick up where I left off.
> It involves compiling a C program, it could break something in a not pure
> Linux environment...
Well, the idea was that if this worked, it'd be generally useful. After all=
,=20
env is on every system, and many Ruby scripts rely on that. So again, not=20
something specific to your program.
|
|
0
|
|
|
|
Reply
|
David
|
12/12/2009 7:43:32 PM
|
|
El S=C3=A1bado, 12 de Diciembre de 2009, David Masover escribi=C3=B3:
> On Saturday 12 December 2009 03:53:06 am I=C3=B1aki Baz Castillo wrote:
> > Well, usually daemons are coded to deelte the pidfile upon receipt of a
> > SIGINT signal (or some others). But if the daemon is killed with "kill
> > -9 PID" then it terminates inmediately without deleting the piddile.
>=20
> True. I tried (and failed) to find an example of this working. However, a
> separate process can watch your process and clean up after it however it
> dies. I think this is the principle behind letting init handle it -- take
> "upstart".
I should take a deep look to "upstart". Until now I'm just used to usual Li=
nux=20
init scripts. But since Debian will adopt upstart it's good time to learn i=
t=20
:)
> > In the case of a crash or segmentfault the daemon wouldn't delete the
> > pidfile again.
>=20
> If the crash raises an exception, you can catch that.
Yes, I catch all the exceptions, I meant segfaults that can occur when usin=
g=20
Ruby C extensions (or when a Ruby bug occurs).
> Segmentation faults
> trigger SIGSEGV, which you can trap.
Ops, I didn't know it at all. Really interesting.
> I suspect you'd have a chance to at
> least fire that unlink call with any death except a 'kill -9'.
Ok, so do you say that using "upstart" this problem could be solved as upst=
art=20
itself could manage it when detects a service crash?
> > To summarize this is possible in these cases:
> >
> > a) Hardcoding the ruby location (avoiding using "env").
> > Not user-friendly.
>=20
> However, if you distribute your app as a gem, this problem actually goes
> away. Here's the top of gems/rake-0.8.7/bin/rake:
>=20
> #!/usr/bin/env ruby
>=20
> #--
> # Copyright (c) 2003, 2004, 2005, 2006, 2007 Jim Weirich
> ...
>=20
> Here's what it actually installs into your PATH:
>=20
> #!/usr/bin/ruby1.9.1
> #
> # This file was generated by RubyGems.
> So, that gives you the best of both worlds -- it's actually somewhat like
> one of the crazier solutions I suggested.
Great. However I'm not sure if my program would fit well as a gem. It's not=
a=20
library or utility but a whole http server (for XCAP protocol). This is, it=
=20
will have conf files into /etc directory and so. I've never seen a gem that=
=20
installs a server by itself and contains files in /etc.
Also, I need a Debian init/upstart script so a gem is not fully valid for m=
e.
=20
Thanks a lot for your help.
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/12/2009 9:54:00 PM
|
|
On Saturday 12 December 2009 03:54:00 pm I=C3=B1aki Baz Castillo wrote:
> El S=C3=A1bado, 12 de Diciembre de 2009, David Masover escribi=C3=B3:
> > I suspect you'd have a chance to at
> > least fire that unlink call with any death except a 'kill -9'.
>=20
> Ok, so do you say that using "upstart" this problem could be solved as
> upstart itself could manage it when detects a service crash?
I'm saying most aspects of it can be solved within the program -- anything=
=20
except 'kill -9'. With something like upstart, even that should be solvable=
=2E=20
On OS X, I think launchd is similar. Basically, you have one (or more) cent=
ral=20
process(es) which manage the launching and killing of daemons.
At this point, you don't even have to use pidfiles, you can just use=20
variables. In pseudocode:
class Process
def start
unless running?
if @pid =3D fork
waitpid(@pid) do
@pid =3D nil
end
else
exec @cmdline
end
end
end
def stop
kill @pid
end
end
The main reason that's pseudocode is that upstart very likely already does=
=20
this for you (so why reinvent the wheel in Ruby?), and because waitpid does=
n't=20
actually work that way.
But basically, the only problem with this model is that if the process=20
responsible for watching your process dies abnormally, either the pidfile=20
won't be cleaned up (if there is one), or you'll now have an unmonitored co=
py=20
of your process running (so you'll need something like killall again). If=20
you're using something like upstart, that's not really a problem -- remembe=
r,=20
upstart is init, which means the second it dies, the kernel panics. In othe=
r=20
words, it doesn't die.
> > So, that gives you the best of both worlds -- it's actually somewhat li=
ke
> > one of the crazier solutions I suggested.
>=20
> Great. However I'm not sure if my program would fit well as a gem. It's n=
ot
> a library or utility but a whole http server (for XCAP protocol). This i=
s,
> it will have conf files into /etc directory and so. I've never seen a gem
> that installs a server by itself and contains files in /etc.
The usual approach I'd suggest here is, store a configfile path, something=
=20
like the PATH variable, in which later configfiles override values set by=20
earlier ones. Then, set all the default values in a sample config file insi=
de=20
your gem, and let the admin put a conf file in /etc/rb_app (or in ~/.rb_app=
,=20
or in a place specified by the environment variable RB_APP_CONFIG, or in a=
=20
place specified by --config on the commandline) if they want to override=20
something.
That just leaves this part:
> Also, I need a Debian init/upstart script so a gem is not fully valid for
> me.
That much is possibly true -- you'd need a script that installs/updates tha=
t=20
script.
If you're worried about people going so far as to have separate Ruby=20
interpreters, I'd suggest letting them write their own script, and simply=20
provide documentation, and maybe a command to install some default samples.=
=20
Those scripts would likely be very simple anyway.
On the other hand, you might consider just building a Debian package,=20
depending on the interpreter you want, and hardcoding it into the shebang a=
nd=20
the upstart scripts. Let people download the source if they want to tweak i=
t=20
further. But I'd only go this route if you're content to depend on the Ruby=
=20
libraries that are already packaged in Debian -- unlike some other package=
=20
managers, apt lacks a way to depend directly on truly alien packages.=20
(Contrast to Gobo, in which system packages can depend directly on gems, CP=
AN=20
modules, etc -- I know Gentoo could depend on CPAN modules, too.)
|
|
0
|
|
|
|
Reply
|
David
|
12/12/2009 10:29:50 PM
|
|
El S=C3=A1bado, 12 de Diciembre de 2009, David Masover escribi=C3=B3:
> On Saturday 12 December 2009 03:54:00 pm I=C3=B1aki Baz Castillo wrote:
> > El S=C3=A1bado, 12 de Diciembre de 2009, David Masover escribi=C3=B3:
> > > I suspect you'd have a chance to at
> > > least fire that unlink call with any death except a 'kill -9'.
> >
> > Ok, so do you say that using "upstart" this problem could be solved as
> > upstart itself could manage it when detects a service crash?
>=20
> I'm saying most aspects of it can be solved within the program -- anything
> except 'kill -9'. With something like upstart, even that should be
> solvable. On OS X, I think launchd is similar. Basically, you have one (=
or
> more) central process(es) which manage the launching and killing of
> daemons.
>=20
> At this point, you don't even have to use pidfiles, you can just use
> variables. In pseudocode:
>=20
> class Process
> def start
> unless running?
> if @pid =3D fork
> waitpid(@pid) do
> @pid =3D nil
> end
> else
> exec @cmdline
> end
> end
> end
> def stop
> kill @pid
> end
> end
>=20
> The main reason that's pseudocode is that upstart very likely already does
> this for you (so why reinvent the wheel in Ruby?), and because waitpid
> doesn't actually work that way.
>=20
> But basically, the only problem with this model is that if the process
> responsible for watching your process dies abnormally, either the pidfile
> won't be cleaned up (if there is one), or you'll now have an unmonitored
> copy of your process running (so you'll need something like killall
> again). If you're using something like upstart, that's not really a
> problem -- remember, upstart is init, which means the second it dies, the
> kernel panics. In other words, it doesn't die.
It's really great and makes lots of sense. The classic usage of pidfiles an=
d=20
so seems ugly and "deprecated" stuff.
> > > So, that gives you the best of both worlds -- it's actually somewhat
> > > like one of the crazier solutions I suggested.
> >
> > Great. However I'm not sure if my program would fit well as a gem. It's
> > not a library or utility but a whole http server (for XCAP protocol).
> > This is, it will have conf files into /etc directory and so. I've never
> > seen a gem that installs a server by itself and contains files in /etc.
>=20
> The usual approach I'd suggest here is, store a configfile path, something
> like the PATH variable, in which later configfiles override values set by
> earlier ones. Then, set all the default values in a sample config file
> inside your gem, and let the admin put a conf file in /etc/rb_app (or in
> ~/.rb_app,
But can a gem installation generate a default conf file/directory in /etc?
I know gem installations can generate runnable files into /usr/bin (or=20
/usr/local/bin). This is, I wouldn't like that the user has to create by=20
himself the config fiel/directory in /etc :(
> or in a place specified by the environment variable
> RB_APP_CONFIG, or in a place specified by --config on the commandline) if
> they want to override something.
I like --config option as I already have command line options for chossing=
=20
logging directory, process uid/gid, listening port and so. Command line=20
options override values in the configuration file.
> On the other hand, you might consider just building a Debian package,
> depending on the interpreter you want, and hardcoding it into the shebang
> and the upstart scripts.
The problem is that my server requires 6-7 gems and modern version of them=
=20
(for example Debian Lenny just includes Rack version 0.3 !! while current g=
em=20
version is 1.0.1 !!).
> Let people download the source if they want to
> tweak it further. But I'd only go this route if you're content to depend
> on the Ruby libraries that are already packaged in Debian -- unlike some
> other package managers, apt lacks a way to depend directly on truly alien
> packages. (Contrast to Gobo, in which system packages can depend directly
> on gems, CPAN modules, etc -- I know Gentoo could depend on CPAN modules,
> too.)
This is the reason why I prefer to build a Gem rather than a deb package.=20
Creating the former would require package all the gems withing the deb pack=
age=20
which would make difficult to upgrade gems and so.
Well, after this good thread (thanks a lot) I think I'll do the following:
=2D A gem package depending on others gems (as usual).
=2D Some runnable Ruby scripts (built into the gem) like:
- myprogram_create_conf.rb: Creates conf files under /etc.
- myprogram_create_init.rb: Creates the init script.
- myprogram_create_database.rb: Creates database for the server.
These scripts could have different behaviour depending on the detected Linu=
x=20
distribution, this is, when running "myprogram_create_init.rb" would detect=
=20
the Linux distribution and offer different kinds of init scripts (and why n=
ot:=20
a upstart script for Ubuntu/Debian !).
Thanks a lot!
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/12/2009 11:29:25 PM
|
|
El S=C3=A1bado, 12 de Diciembre de 2009, Shot (Piotr Szotkowski) escribi=C3=
=B3:
> I=C3=B1aki Baz Castillo:
> > However in /proc/PID/status I still have the same described
> > issues: "Name: ruby1.9", so I cannot do "killall rb_program".
> >
> > This can be solved by using:
> > #!/usr/local/bin/ruby1.9
> > rather than:
> > #!/usr/bin/env ruby1.9
> >
> > but of course hardcoding the location of ruby is not very good
> > approach (specially when you want your code to run on any Linux
> > system).
>=20
> I was wondering about exactly this problem recently. I=E2=80=99m using
> hand-rolled Ruby 1.9.1 and 1.8.7 versions in ~/opt =E2=80=93 and once I f=
inally
> got to rolling my own gem I found out that when RubyGems install an
> executable, they put a wrapper script in the given Ruby installation
> path, with the hashbang hardcoded to that interpreter=E2=80=99s binary.
I suffer same issues. I've installed ruby 1.9.1 (installed from sources) un=
der=20
/usr/local. and ruby 1.8.7 (Debian package) under /usr.
I compile ruby1.9 with these options:
/configure --prefix=3D/usr/local/ --program-suffix=3D1.9 ; make ; make in=
stall
so all its runnable files are sufixed by 1.9 (ruby1.9, gem1.9, irb1.9...).
Unfortunatelly executables installed by gems are not sufixed so there is=20
conflict between ruby1.8 gems and ruby1.9 gems.
By default /usr/local/bin/ appears before than /usr/bin/ in usual PATH=20
environment variable, so executables belonging to ruby1.9 gems take=20
preference. This is ugly when you install a ruby1.8 gem which requires some=
=20
ruby executtable (as racc, rake and so).
So finally my "solution/workaround" is a script that rewrites the PATH=20
variable and sets /usr/bin/ before /usr/local/bin/. And I must run it befor=
e=20
installing a gem for ruby1.8. Ugly but works :)
> In other words =E2=80=93 while the executables in my repo start with
> =E2=80=98#!/usr/bin/env ruby=E2=80=99 (and so pick up the =E2=80=98curren=
t=E2=80=99 Ruby interpreter),
> once I roll and install a gem RubyGems create a custom executable
> wrappers for them, and the ones installed with Ruby 1.9.1 start with
> =E2=80=98#!/home/shot/opt/ruby-1.9.1-p376/bin/ruby=E2=80=99 (and if I lin=
k them from
> my ~/bin I don=E2=80=99t even need to do any $PATH munging to get them ru=
nning
> through a given Ruby binary).
>=20
> Hence, my conclusion is that if you turned your code into a gem prior
> to installing it, you could still keep the =E2=80=98#!/usr/bin/env ruby1.=
9=E2=80=99
> hashbang in your repo (and for testing), but once you want to get
> a given version into =E2=80=98production=E2=80=99, RubyGems will turn tha=
t into
> =E2=80=98#!/usr/local/bin/ruby1.9=E2=80=99 upon the gem=E2=80=99s install=
ation.
Ok, I'll do it.
Thanks a lot.
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/12/2009 11:36:30 PM
|
|
El S=E1bado, 12 de Diciembre de 2009, Robert Klemme escribi=F3:
> This is what I would do:
>=20
> VAR=3D'/var/run'
>=20
> pid_file =3D File.join(VAR, File.basename($0) + '.pid')
>=20
> begin
> old_pid =3D File.read(pid_file).to_i
> Process.kill 0, old_pid
> $stderr.puts "ERROR: already running with PID #{old_pid}"
> exit 1
> rescue Errno::ENOENT
> # no pid file
> rescue Errno::ESRCH
> # process not running
> $stderr.puts 'WARNING: stale pid file'
> end
>=20
> # open file with EXCL in order to catch race conditions where two
> # processes were started almost at the same time and both thought
> # they would be a new instance. Uncomment sleep to simulate:
> # sleep 2
> File.open(pid_file, File::EXCL | File::WRONLY | File::CREAT) {|io|=20
> io.write($$)}
> trap(0) {File.delete pid_file}
>=20
> puts "OK, here we go."
Let me a question: is the above a fragment of a Linux init script written i=
n=20
Ruby (rather than bash/sh as usual)?
If so, according to LSB specifications it should return 0 (success) in case=
of=20
"start" action when the daemon is already running.
Thanks a lot.
=2D-=20
I=F1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
iso
|
12/12/2009 11:51:02 PM
|
|
On Saturday 12 December 2009 05:29:25 pm I=C3=B1aki Baz Castillo wrote:
> El S=C3=A1bado, 12 de Diciembre de 2009, David Masover escribi=C3=B3:
> > The usual approach I'd suggest here is, store a configfile path,
> > something like the PATH variable, in which later configfiles override
> > values set by earlier ones. Then, set all the default values in a sample
> > config file inside your gem, and let the admin put a conf file in
> > /etc/rb_app (or in ~/.rb_app,
>=20
> But can a gem installation generate a default conf file/directory in /etc?
Short answer: no.
> I know gem installations can generate runnable files into /usr/bin (or
> /usr/local/bin).
No, they can't.
What they can do is provide a runnable file, which the gem system installs =
to=20
wherever it's configured to install to. I have a completely separate user f=
or=20
each version of Ruby I install, each with their own gems -- my 1.9 rubygems=
=20
install their scripts to /home/ruby19/home/bin.
I like that, because it's easy enough to add and remove PATH elements, yet =
if=20
something goes horribly wrong, I can always completely blow away=20
/home/ruby19/home (the GEM_HOME path) and rebuild it. If I'd let it install=
=20
binaries to the system path (/usr/bin or /usr/local/bin), it'd be much hard=
er=20
to sort out which were installed by gems and which weren't, unless I was=20
willing to manually uninstall each one. But part of the point of doing it t=
his=20
way is that Rubygems itself might break, so that doesn't really work.
So, basically, right now, Rubygems has explicit support for installing scri=
pts=20
into _somewhere_ in your path, just as it has explicit support for installi=
ng=20
libraries into _somewhere_ into $: -- and in both cases, you, as a gem=20
developer, have no control over where that will eventually be.
> This is, I wouldn't like that the user has to create by
> himself the config fiel/directory in /etc :(
That's why I suggested creating a script that doesn't run on installation, =
but=20
at the user's discretion. Or you could have it run when the app first launc=
hes=20
=2D- Wine is like that.
It looks like that's what you decided to do, though.
|
|
0
|
|
|
|
Reply
|
David
|
12/12/2009 11:57:34 PM
|
|
El Domingo, 13 de Diciembre de 2009, David Masover escribi=C3=B3:
> On Saturday 12 December 2009 05:29:25 pm I=C3=B1aki Baz Castillo wrote:
> > El S=C3=A1bado, 12 de Diciembre de 2009, David Masover escribi=C3=B3:
> > > The usual approach I'd suggest here is, store a configfile path,
> > > something like the PATH variable, in which later configfiles override
> > > values set by earlier ones. Then, set all the default values in a
> > > sample config file inside your gem, and let the admin put a conf file
> > > in /etc/rb_app (or in ~/.rb_app,
> >
> > But can a gem installation generate a default conf file/directory in
> > /etc?
>=20
> Short answer: no.
>=20
> > I know gem installations can generate runnable files into /usr/bin (or
> > /usr/local/bin).
>=20
> No, they can't.
>=20
> What they can do is provide a runnable file, which the gem system installs
> to wherever it's configured to install to. I have a completely separate
> user for each version of Ruby I install, each with their own gems -- my
> 1.9 rubygems install their scripts to /home/ruby19/home/bin.
>=20
> I like that, because it's easy enough to add and remove PATH elements, yet
> if something goes horribly wrong, I can always completely blow away
> /home/ruby19/home (the GEM_HOME path) and rebuild it. If I'd let it insta=
ll
> binaries to the system path (/usr/bin or /usr/local/bin), it'd be much
> harder to sort out which were installed by gems and which weren't, unless
> I was willing to manually uninstall each one. But part of the point of
> doing it this way is that Rubygems itself might break, so that doesn't
> really work.
>=20
> So, basically, right now, Rubygems has explicit support for installing
> scripts into _somewhere_ in your path, just as it has explicit support f=
or
> installing libraries into _somewhere_ into $: -- and in both cases, you,
> as a gem developer, have no control over where that will eventually be.
Clear now, thanks a lot.
> > This is, I wouldn't like that the user has to create by
> > himself the config fiel/directory in /etc :(
>=20
> That's why I suggested creating a script that doesn't run on installation,
> but at the user's discretion. Or you could have it run when the app first
> launches -- Wine is like that.
>=20
> It looks like that's what you decided to do, though.
=20
Yes, thanks to this thread :)
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/13/2009 12:52:13 AM
|
|
On 13.12.2009 00:51, I=F1aki Baz Castillo wrote:
> El S=E1bado, 12 de Diciembre de 2009, Robert Klemme escribi=F3:
>> This is what I would do:
>>
>> VAR=3D'/var/run'
>>
>> pid_file =3D File.join(VAR, File.basename($0) + '.pid')
>>
>> begin
>> old_pid =3D File.read(pid_file).to_i
>> Process.kill 0, old_pid
>> $stderr.puts "ERROR: already running with PID #{old_pid}"
>> exit 1
>> rescue Errno::ENOENT
>> # no pid file
>> rescue Errno::ESRCH
>> # process not running
>> $stderr.puts 'WARNING: stale pid file'
>> end
>>
>> # open file with EXCL in order to catch race conditions where two
>> # processes were started almost at the same time and both thought
>> # they would be a new instance. Uncomment sleep to simulate:
>> # sleep 2
>> File.open(pid_file, File::EXCL | File::WRONLY | File::CREAT) {|io|
>> io.write($$)}
>> trap(0) {File.delete pid_file}
>>
>> puts "OK, here we go."
>
>
> Let me a question: is the above a fragment of a Linux init script writt=
en in
> Ruby (rather than bash/sh as usual)?
That was hacked together for demonstration purposes. It was not=20
intended as an init script but rather as the demon itself - albeit=20
without all the demonization stuff (detaching from terminal etc.)=20
because I wanted to focus on the aspect of pid file handling and killing.=
> If so, according to LSB specifications it should return 0 (success) in =
case of
> "start" action when the daemon is already running.
Well, if you write a start script for that "ruby demon" you would have=20
to handle exit codes properly.
Kind regards
robert
--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
|
|
0
|
|
|
|
Reply
|
Robert
|
12/13/2009 11:10:02 AM
|
|
El Domingo, 13 de Diciembre de 2009, Robert Klemme escribi=F3:
> On 13.12.2009 00:51, I=F1aki Baz Castillo wrote:
> > El S=E1bado, 12 de Diciembre de 2009, Robert Klemme escribi=F3:
> >> This is what I would do:
> >>
> >> VAR=3D'/var/run'
> >>
> >> pid_file =3D File.join(VAR, File.basename($0) + '.pid')
> >>
> >> begin
> >> old_pid =3D File.read(pid_file).to_i
> >> Process.kill 0, old_pid
> >> $stderr.puts "ERROR: already running with PID #{old_pid}"
> >> exit 1
> >> rescue Errno::ENOENT
> >> # no pid file
> >> rescue Errno::ESRCH
> >> # process not running
> >> $stderr.puts 'WARNING: stale pid file'
> >> end
> >>
> >> # open file with EXCL in order to catch race conditions where two
> >> # processes were started almost at the same time and both thought
> >> # they would be a new instance. Uncomment sleep to simulate:
> >> # sleep 2
> >> File.open(pid_file, File::EXCL | File::WRONLY | File::CREAT) {|io|
> >> io.write($$)}
> >> trap(0) {File.delete pid_file}
> >>
> >> puts "OK, here we go."
> >
> > Let me a question: is the above a fragment of a Linux init script writt=
en
> > in Ruby (rather than bash/sh as usual)?
>=20
> That was hacked together for demonstration purposes. It was not
> intended as an init script but rather as the demon itself - albeit
> without all the demonization stuff (detaching from terminal etc.)
> because I wanted to focus on the aspect of pid file handling and killing.
Ok ok, I just asked as curiosity because some time ago I tryed to do a init=
=20
script in Ruby and couldn't do it properly... not remember the reason right=
=20
now...
> > If so, according to LSB specifications it should return 0 (success) in
> > case of "start" action when the daemon is already running.
>=20
> Well, if you write a start script for that "ruby demon" you would have
> to handle exit codes properly.
Ok, so later the init script could get "1" and return "0" as LSB states.
Thanks a lot again.
=2D-=20
I=F1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
iso
|
12/13/2009 12:55:43 PM
|
|
El Domingo, 13 de Diciembre de 2009, Shot (Piotr Szotkowski) escribi=C3=B3:
> I=C3=B1aki Baz Castillo:
> > I suffer same issues. I've installed ruby 1.9.1 (installed from
> > sources) under /usr/local. and ruby 1.8.7 (Debian package) under /usr.
> >
> > I compile ruby1.9 with these options:
> > /configure --prefix=3D/usr/local/ --program-suffix=3D1.9 ; make ; make
> > install so all its runnable files are sufixed by 1.9 (ruby1.9, gem1.9,
> > irb1.9...).
>=20
> I think a much simpler solutions are to either (a) use rvm (which
> doesn=E2=80=99t work for me for some reason) or (b) use my approach (belo=
w).
>=20
> I don=E2=80=99t use program suffixes, but rather use
>=20
> ./configure --prefix=3D/home/shot/opt/ruby-1.9.1-p376
>=20
> (and similar, for example ~/opt/ruby-1.8.7-git when building 1.8.7 from
> the repo=E2=80=99s latest 1.8.7 revision) plus ~/opt/ruby-1.8 and ~/opt/r=
uby-1.9
> symlinks poiting to the hand-compiled versions I want to use for my
> development. I then have
>=20
> export PATH_ORIG=3D"$PATH"
>=20
> at the end of my ~/.bashrc and
>=20
> alias r18=3D'export PATH=3D/home/shot/opt/ruby-1.8/bin:$PATH_ORIG'
> alias r19=3D'export PATH=3D/home/shot/opt/ruby-1.9/bin:$PATH_ORIG'
>=20
> in my ~/.bash_aliases, and switching between Ruby 1.8 and 1.9 is as
> quick as running =E2=80=98r18=E2=80=99 and =E2=80=98r19=E2=80=99 in the s=
hell. I leave system-packaged
> Ruby alone, if only so that =E2=80=98gem update --system=E2=80=99 works s=
anely (and so
> no sudo is required for any of my Ruby development whatsoever).
>=20
> Of course, if you want to have system-wide hand-compiled Ruby 1.8 and/or
> 1.9, putting them in /opt (rather than ~/opt) might be more elegant.
This is a very nice solution. However the problem is that I need ruby1.8 de=
b=20
package isntalled in my system as many other packages require ruby1.8, and =
it=20
is installed under /usr/ as usual.
=2D-=20
I=C3=B1aki Baz Castillo <ibc@aliax.net>
|
|
0
|
|
|
|
Reply
|
utf
|
12/13/2009 12:56:03 PM
|
|
On 13.12.2009 13:55, I=F1aki Baz Castillo wrote:
> El Domingo, 13 de Diciembre de 2009, Robert Klemme escribi=F3:
>> On 13.12.2009 00:51, I=F1aki Baz Castillo wrote:
>>> El S=E1bado, 12 de Diciembre de 2009, Robert Klemme escribi=F3:
>>>> This is what I would do:
>>>>
>>>> VAR=3D'/var/run'
>>>>
>>>> pid_file =3D File.join(VAR, File.basename($0) + '.pid')
>>>>
>>>> begin
>>>> old_pid =3D File.read(pid_file).to_i
>>>> Process.kill 0, old_pid
>>>> $stderr.puts "ERROR: already running with PID #{old_pid}"
>>>> exit 1
>>>> rescue Errno::ENOENT
>>>> # no pid file
>>>> rescue Errno::ESRCH
>>>> # process not running
>>>> $stderr.puts 'WARNING: stale pid file'
>>>> end
>>>>
>>>> # open file with EXCL in order to catch race conditions where two
>>>> # processes were started almost at the same time and both thought
>>>> # they would be a new instance. Uncomment sleep to simulate:
>>>> # sleep 2
>>>> File.open(pid_file, File::EXCL | File::WRONLY | File::CREAT) {|io|
>>>> io.write($$)}
>>>> trap(0) {File.delete pid_file}
>>>>
>>>> puts "OK, here we go."
>>> Let me a question: is the above a fragment of a Linux init script wri=
tten
>>> in Ruby (rather than bash/sh as usual)?
>> That was hacked together for demonstration purposes. It was not
>> intended as an init script but rather as the demon itself - albeit
>> without all the demonization stuff (detaching from terminal etc.)
>> because I wanted to focus on the aspect of pid file handling and killi=
ng.
>=20
> Ok ok, I just asked as curiosity because some time ago I tryed to do a =
init=20
> script in Ruby and couldn't do it properly... not remember the reason r=
ight=20
> now...
One small thing just comes to mind: you can replace the "trap(0) {..."=20
with "at_exit {...". This is probably a bit more rubyish. It also has=20
the advantage that you can have multiple at_exit handlers while you can=20
only have one trap:
robert@fussel ~
$ ruby19 -e '2.times {|i| at_exit { puts "exiting #{i}..."} }'
exiting 1...
exiting 0...
robert@fussel ~
$ ruby19 -e '2.times {|i| trap(0) { puts "exiting #{i}..."} }'
exiting 1...
robert@fussel ~
$
>>> If so, according to LSB specifications it should return 0 (success) i=
n
>>> case of "start" action when the daemon is already running.
>> Well, if you write a start script for that "ruby demon" you would have=
>> to handle exit codes properly.
>=20
> Ok, so later the init script could get "1" and return "0" as LSB states=
=2E
Exactly.
> Thanks a lot again.
You're welcome!
Kind regards
robert
--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
|
|
0
|
|
|
|
Reply
|
Robert
|
12/13/2009 2:05:06 PM
|
|
|
24 Replies
126 Views
(page loaded in 0.181 seconds)
Similiar Articles: Generating all possible combinations of a 5 digit pattern. - comp ...... against a pre-defined list of possible patterns, until the program ... was going to do was brute-force ... generate a few hundred possible schedules with different ... IBM COBOL Migration to Windows COBOL - comp.lang.cobolBecause of the tier separation, it is usually possible to ... some scripting language, like Perl, Python, REXX, Ruby. ... converted to environment variables with the same name ... Can a procedure contain only a SELECT statement? - comp.databases ...... resultset, PL/SQL is a *REAL* programming language, which doesn't force you to ... jpl as set notcount on select name ... to get two result sets which are different ... some GPIB-tcl questions - comp.lang.tclAn example program, which displays a ... I think it is also not possible to ibrda() simultaneously on more than one device. ... Start Application Pool - comp.lang.ruby ... Ruby (programming language) - Wikipedia, the free encyclopediaEach takes a different approach, with IronRuby ... purpose of Ruby language." Choice of the name "Ruby" ... begin statement end until expression in Ruby will in fact run the ... Programming Ruby: The Pragmatic Programmer's Guide... as possible, so we want our code to run ... But Ruby is fundamentally different. It is a true programming ... program. You can simply run Ruby giving the script name as an ... 7/26/2012 12:17:02 AM
|