Re: Strange behavior with job control

2010-07-27 Thread Andreas Schwab
Christoph Dittmann  writes:

> Why is "sleep 5" still running in the second case even though the job
> received SIGTERM and is known to the job control as "terminated"?

Try adding "ps f" before the wait command to see the difference in how
bash executes the two cases.  In the case without the braces the
subshell replaces itself with the sleep command, which is what is then
killed.  In the other case with the braces the subshell executes the
sleep as a subprocess and waits for it to terminate.  The kill command
then kills the subshell but the sleep command continues.

If you want to kill the whole background job you need to enable job
control (set -m) and call kill with the job specifier instead (kill %2
in this case).

> How can the wait call affect a job it's not supposed to wait for?

It's a simple race.  You may not give the subshell enough time to
acutally execute the sleep command.

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."



Re: Strange behavior with job control

2010-07-27 Thread Christoph Dittmann
On 07/27/2010 12:05 PM, Andreas Schwab wrote:
> If you want to kill the whole background job you need to enable job
> control (set -m) and call kill with the job specifier instead (kill %2
> in this case).
> 
>> How can the wait call affect a job it's not supposed to wait for?
> 
> It's a simple race.  You may not give the subshell enough time to
> acutally execute the sleep command.

Hi Andreas,

thanks a lot. I suspected it might be something simple like that. "set
-m" solved the problem for me.

What I was going for was a script which executes another command with a
timeout. This is what I now came up with:


#!/bin/bash

if [[ $# -lt 2 ]]; then
echo "Usage: $(basename $0) timeout_in_seconds commandline..."
echo "Runs the command and sends SIGTERM to the child after the
specified timeout."
exit 0
fi

# Enable job control.
set -mb

TIMEOUT="$1"
shift

# Use SIGUSR1 to interrupt the wait call.
trap ':' USR1

# Run the desired command.
"$@" &

# Suppress any output from now on.
exec &>/dev/null
# Run the watchdog.
{ sleep $TIMEOUT ; kill -USR1 $$; } &

# Give the command a chance to complete.
wait %1
EXIT_STATUS=$?

# Send SIGTERM to the watchdog and the command. If a job is not
# running, the kill has no effect.
kill %2
kill %1

exit $EXIT_STATUS


It works in all my test cases. Because I'm still learning to write bash
scripts, I'd be very interested to know if there are any obvious
blunders in the way I did it (or more subtle mistakes).

Also, is there a more elegant way to achieve the same effect? I thought
running a process with a time limit would not be such an unlikely thing
to do.

Christoph



Re: Strange behavior with job control

2010-07-27 Thread Eric Blake
On 07/27/2010 05:44 AM, Christoph Dittmann wrote:
> What I was going for was a script which executes another command with a
> timeout.

If you can assume the presence of GNU coreutils, use timeout(1).  Much
nicer for this particular task.

Otherwise, I did not review your script for accuracy.

-- 
Eric Blake   ebl...@redhat.com+1-801-349-2682
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


Re: Strange behavior with job control

2010-07-27 Thread Christoph Dittmann
On 07/27/2010 02:05 PM, Eric Blake wrote:
> On 07/27/2010 05:44 AM, Christoph Dittmann wrote:
>> What I was going for was a script which executes another command with a
>> timeout.
> 
> If you can assume the presence of GNU coreutils, use timeout(1).  Much
> nicer for this particular task.

Thanks, I'll look into this.

OK, it looks like timeout(1) is in coreutils starting with version
7.5-1, and unfortunately Ubuntu 10.04 only offers coreutils-7.4-2 with
timeout in a separate package.

According to the manpage, timeout does precisely what I need. I'll
definitely remember that program, thanks. It's probably a cleaner way
than implementing a bash script to do the same task manually.

Christoph



Re: When to use printf instead of echo?

2010-07-27 Thread Greg Wooledge
On Mon, Jul 26, 2010 at 04:27:30PM -0500, Peng Yu wrote:
> Could you
> please let me know when to use printf instead of echo?

There is never any need to use echo.  printf does everything echo does,
and does it better -- but people are comfortable with echo, because it's
simple, and they've been trained by 15 years of legacy scripts that used
it.

> In particular, I want to print a string that has single quote, double
> quote and dollar character.

printf "%s\n" "$mystring"

It makes no difference what the contents of the variable are.

> I could use " to enclose such string and
> add '\' to escape " and $ in the string.

Oh, you mean to express a string constant in the code?  That has nothing
at all to do with the commands you give it to.

mystring='whatever'$'whatever'"whatever"\w\h\a\t\e\v\e\r

Do whatever it takes.  Concatenate multiple quoting styles as needed.

Back to your specific complaint:

> In particular, I want to print a string that has single quote, double
> quote and dollar character.

Meaning "I want to create a string constant that contains a single quote,
a double quote and a dollar sign."

Style 1: \'\"\$
Style 2: \''"$'
Style 3: "'\"\$"
Style 4: $'\'"$'
etc.

At this point it's a matter of personal choice.  Pick whichever style
looks least ugly to you.  There are an infinite number of ways you could
write this (if you discard the ways that simply append '' and the like
to the constant for no reason, it becomes finite, but I have no intention
of counting them all).



Re: Strange behavior with job control

2010-07-27 Thread Greg Wooledge
On Tue, Jul 27, 2010 at 01:44:26PM +0200, Christoph Dittmann wrote:
> What I was going for was a script which executes another command with a
> timeout.

http://mywiki.wooledge.org/BashFAQ/068
http://mywiki.wooledge.org/XyProblem



Re: Strange behavior with job control

2010-07-27 Thread Christoph Dittmann
On 07/27/2010 02:35 PM, Greg Wooledge wrote:
> On Tue, Jul 27, 2010 at 01:44:26PM +0200, Christoph Dittmann wrote:
>> What I was going for was a script which executes another command with a
>> timeout.
> 
> http://mywiki.wooledge.org/BashFAQ/068
The process I want to put under the timeout does not offer a timeout
setting by itself (see below).
The bash script http://www.shelldorado.com/scripts/cmds/timeout
lets the watchdog stay around long after the command has finished:
$ ./timeout -t 60 echo done; sleep 1; ps aux | grep '[s]leep'
done
100023115  0.0  0.0   9728   828 pts/1S15:00   0:00 sleep 60

timeout(1) looks like the way to go. The only thing I don't like is that
it is not installed on a standard debian or ubuntu system. That's why I
was hoping for a solution in bash.

> http://mywiki.wooledge.org/XyProblem

Oh, shame on me. :/

I can see how such a script looks like a really bad idea.

Just for the background: I run "darcs pull" in a cronjob every few hours
to mirror a darcs repository. If the darcs server happens to be offline
or not answering properly, it can happen that "darcs pull" hangs for
hours without doing anything. This happened only once so far and I
couldn't reproduce the circumstances. However, it broke the cronjob
because the hanging darcs process kept a lock in the local repository.
Just to avoid this I wanted to place a (relatively high) timeout on
"darcs pull" so that the repository is not locked indefinitely if
something goes wrong.

Christoph



Re: RFE -or- Howto?

2010-07-27 Thread Linda Walsh
Huh. Triple redirect...  Thanks!


On 7/26/2010 5:53 PM, Chet Ramey wrote:
> On 7/26/10 6:25 PM, Linda Walsh wrote:
>>  I don't know if there's an easy way, but if not would you consider an
>> RFE --
>>
>> Is there a syntax for a mult-var assignment, ala:
>> (a b c d)=(1 2 3 4)
> 
> Yes.
> 
> read a b c d <<<"1 2 3 4"
> 
> Chet



crash when using associative array and integer variable

2010-07-27 Thread Roman Rakus

Repeated in the bash-4.0.38 and bash-4.1.7 by the script;
#!/bin/bash

typeset -Ai s
y='*'
z='['
s[$y]=1
s[$z]=2
(( s[$z] = s[$z] + ${s[$y]} ))
(( s[$y] = s[$y] + ${s[$z]} ))
[[ ${s[$y]} = 4  ]] && echo "ok"


FIX: added check;
diff -up bash-4.1/variables.c.Ai bash-4.1/variables.c
--- bash-4.1/variables.c.Ai 2010-07-28 08:42:54.0 +0200
+++ bash-4.1/variables.c2010-07-28 08:43:17.0 +0200
@@ -2371,7 +2371,7 @@ bind_int_variable (lhs, rhs)
 #endif
 v = bind_variable (lhs, rhs, 0);

-  if (isint)
+  if (isint && v)
 VSETATTR (v, att_integer);

   return (v);

RR