Differences between revisions 6 and 12 (spanning 6 versions)
Revision 6 as of 2007-04-24 01:09:31
Size: 3149
Editor: WillDye
Comment:
Revision 12 as of 2010-01-15 17:25:15
Size: 5741
Editor: WillDye
Comment: Emphasize that some non-working draft code is indeed not working
Deletions are marked like this. Additions are marked like this.
Line 15: Line 15:
mostly in the XP and Red Hat varieties. mostly in the Vista and Ubuntu varieties.
Line 31: Line 31:
== Personal sandbox area ==
Line 42: Line 44:
Anyway, here's some very simple Bash and Tcl code
which allows the desktop machine to
easily listen for events from the other machines.
Line 46: Line 45:
First, a quick test to see if it can work on your system. Here's some very simple Bash and Tcl code
which demonstrates a basic framework
that you could use to create such a system.
It's based on the ability of Bash to use "/dev/tcp"
as a way to easily send messages to TCP ports.
Line 51: Line 55:
tclsh<<<'proc respond {channel address port} {puts "$channel $address $port [gets $c]"; close $c}; socket -server respond 8765; vwait forever' tclsh<<<'
proc respond {channel address port} {
  
puts "$channel $address $port [gets $c]";
 
close $c};
socket -server respond 8765;
vwait forever'
Line 57: Line 66:
while sleep 3; do date > /dev/tcp/desktop.yourdomain.com/8765; done while sleep 3;
 
do date > /dev/tcp/desktop.yourdomain.com/8765;
done
Line 72: Line 83:
Now you can extend the programs to run some particular program
if some particular condition is satisfied.
Another use is for the server (desktop) side to raise an alert
if a particular client hasn't sent a message in a long time,
indicating that the client has been disconnected.
Now you can extend the programs to start some function
whenever a particular condition is satisfied.

----

(Draft of a possible addition to BashFAQ #45)

Suppose you want the newest instance of a script to
replace any existing instances of the same script.
As before, if you find yourself in this position,
you might want to reconsider your overall approach.
There is no completely satisfactory way to enforce
a single instance of a given script,
because the system simply does not maintain
an unchangeable link between a running process
and the original contents & location
of every file used when the process was created.

All the same, sometimes a buggy script has an
unpleasant tendency to be hard to stop,
or get stuck in certain rare circumstances,
yet it's not enough of a problem to be worth
tracking down and fixing properly.
So, with caveats about unreliability in mind,
here's one way to have
new invocations replace existing ones:

(Addendum: after some testing,
it's clear that this code does NOT work correctly,
and is useful only as a fumbling step towards
something better, or perhaps as a step towards
proving that the whole approach is a bad idea.
I have to confess that I still use it,
not because it works correctly, but because it
at least manages to give me some information
about running processes that I've started.
Maybe someday I'll come back to this code and
fix it right. In the meantime, caveat coder.)
{{{
## WARNING: THIS CODE DOES NOT WORK RIGHT
#!/usr/bin/env bash
# (Insert useful description of the program here)

# Issue a warning if it looks like this script is already running.
if (( $(pgrep -flU$(whoami) $0 | wc -l) > 1 )); then
   sleep 2 # Yes, this delay is ugly, but sometimes process startup...
   # ...briefly shows two instances, so pause a bit and double-check.
   if (( $(pgrep -flU$(whoami) $0 | wc -l) > 1 )); then
       echo "There may be an existing duplicate process running:"
       pgrep -flU$(whoami) $0
       echo "Consider running the following commands, as appropriate:"
       echo " kill -1 "$(pgrep -fU$(whoami) $0|grep -v $$)
       echo " pgrep -flU$(whoami) $0"
       echo " kill -1 \$(pgrep -fU$(whoami) $0|grep -v $$)"
       echo " (The process that was just started is: $$)"
   fi
fi

# (Insert the the rest of the script below)
}}}

If you're feeling really, really bold,
you could make the pkill automatic.
If you're clever enough, however, to make sure that
you never automatically pkill the wrong processes,
then maybe you should apply your ample talents
to avoiding the bugs which got you
into that situation in the first place.
As for me ([[WillDye|WillDye]]),
if I have to kill stale processes,
I want to be reminded that there's a problem.

I'm William L. Dye ("willdye"), a programmer from Lincoln, Nebraska, USA. I'm not a Bash expert, but I've contributed to this wiki in the past, and might contribute again sometime, so I might as well create an account here.

I typically program in C/C++, Tcl/Tk, and Bash; and occasionally program in Python, Awk, and Lisp. I can't even remember all the languages I've used over the years, but it's a long list (Fortran, APL, various assembers, et alibi). I can also use Java. If I have to. I guess.

I currently program on the Windows and Linux platforms, mostly in the Vista and Ubuntu varieties. In the past, I've used IBM mainframes (mostly 370 MVS), BSD, HP/UX, and Macintosh. In acient days of long ago, I've used CP/M, DOS, Amiga, CDC mainframes, TRS-80, Commodore 64, Altair 8800, custom machine controllers (8080 and Z-80), and a bunch of other crufty old things that I can barely even remember now.

Yeah, I'm that old. And just so you know, we really did walk 20 miles to school and back, and it was uphill both ways! And we didn't have your fancy ones and zeros back then. Why, I had to write an entire database with just zeros! Wimps! Learn to program using a soldering iron, ya slackers! Mutter, mutter, mumble...


Personal sandbox area

This is some code that I might post in the Bash FAQ or open questions pages, if I can determine that it's a good solution (or fix the problems, if I can find any). Do NOT trust this code -- it's just a draft.

Suppose you have multiple computers, only one of which operates your desktop environment, and you want the other machines to notify the desktop machine if something noteworthy happens. The definition of "noteworthy" doesn't matter to this example code, but it could be a disk which is getting dangerously full, or incoming mail that matches a certain pattern.

Here's some very simple Bash and Tcl code which demonstrates a basic framework that you could use to create such a system. It's based on the ability of Bash to use "/dev/tcp" as a way to easily send messages to TCP ports.

On the desktop machine, run this at a Bash prompt, or put the equivalent into a Tcl program:

tclsh<<<'
proc respond {channel address port} {
  puts "$channel $address $port [gets $c]";
  close $c};
socket -server respond 8765;
vwait forever'

On the other machine(s), run this Bash program:

while sleep 3;
  do date > /dev/tcp/desktop.yourdomain.com/8765;
done

...where "desktop.yourdomain.com" is the name or I.P. address of your desktop machine.

If that fails, then don't bother making the programs any fancier until you figure out what's wrong. If your firewall is blocking the port, or the port is in use by another program, try some other port.

If it works, then every three seconds or so, you should see the current date appear on the server side. Now you can extend the programs to start some function whenever a particular condition is satisfied.


(Draft of a possible addition to BashFAQ #45)

Suppose you want the newest instance of a script to replace any existing instances of the same script. As before, if you find yourself in this position, you might want to reconsider your overall approach. There is no completely satisfactory way to enforce a single instance of a given script, because the system simply does not maintain an unchangeable link between a running process and the original contents & location of every file used when the process was created.

All the same, sometimes a buggy script has an unpleasant tendency to be hard to stop, or get stuck in certain rare circumstances, yet it's not enough of a problem to be worth tracking down and fixing properly. So, with caveats about unreliability in mind, here's one way to have new invocations replace existing ones:

(Addendum: after some testing, it's clear that this code does NOT work correctly, and is useful only as a fumbling step towards something better, or perhaps as a step towards proving that the whole approach is a bad idea. I have to confess that I still use it, not because it works correctly, but because it at least manages to give me some information about running processes that I've started. Maybe someday I'll come back to this code and fix it right. In the meantime, caveat coder.)

## WARNING: THIS CODE DOES NOT WORK RIGHT
#!/usr/bin/env bash
# (Insert useful description of the program here)

# Issue a warning if it looks like this script is already running.
if (( $(pgrep -flU$(whoami) $0 | wc -l) > 1 )); then
   sleep 2 # Yes, this delay is ugly, but sometimes process startup...
   # ...briefly shows two instances, so pause a bit and double-check.
   if (( $(pgrep -flU$(whoami) $0 | wc -l) > 1 )); then
       echo "There may be an existing duplicate process running:"
       pgrep -flU$(whoami) $0
       echo "Consider running the following commands, as appropriate:"
       echo "  kill -1 "$(pgrep -fU$(whoami) $0|grep -v $$)
       echo "  pgrep -flU$(whoami) $0"
       echo "  kill -1 \$(pgrep -fU$(whoami) $0|grep -v $$)"
       echo "  (The process that was just started is: $$)"
   fi
fi

# (Insert the the rest of the script below)

If you're feeling really, really bold, you could make the pkill automatic. If you're clever enough, however, to make sure that you never automatically pkill the wrong processes, then maybe you should apply your ample talents to avoiding the bugs which got you into that situation in the first place. As for me (WillDye), if I have to kill stale processes, I want to be reminded that there's a problem.


CategoryHomepage

WillDye (last edited 2010-01-15 17:25:15 by WillDye)