I'm keeping an eye on a process in FreeBSD using a script which outputs the current status of the job.
Using the csh
builtin command repeat
, I'd like to run the script every 2 seconds, so naively I'd like to do something like this:
repeat 100000 ./dumpstatus ; sleep 2
Obviously the semicolon won't work as intended, but I can't find the correct syntax to include it.
I can workaround by invoking a new shell instance under repeat
:
repeat 100000 sh -c 'path/to/script/dumpstatus ; sleep 2'
but that's hardly ideal, and doesn't take a path from the current pwd
either which is annoying :)
I've also tried repeat 10000 ( ./dumpstatus ; sleep 2)
with and without escaping the brackets, that doesn't work either and I'm not completely sure why.
What is the correct way to do this, without invoking sh -c
, so the semicolon gets interpreted as I would wish?
2 Answers 2
I believe it's not possible without invoking a shell, as the csh manpage states (in part):
repeat count command
The specified command, which is subject to the same restrictions as the command in the one line if statement above, is executed count times. ...
combined with the if
description:
if ( expr ) command
... command must be a simple command, not an alias, a pipeline, a command list or a parenthesized command list, but it may have arguments.
... seems to me to rule out other options.
I am unable to reproduce your $PWD failure in the sh -c
example. Given this script in my home directory:
$ cat ~/script.sh
#!/bin/sh
echo 0ドル pwd is $PWD
And a sample run of:
$ csh
$ echo $version
tcsh 6.18.01 (Astron) 2012年02月14日 (x86_64-unknown-linux) options wide,nls,dl,al,kan,rh,color,filec
$ cd /tmp
$ repeat 2 sh -c '~/script.sh; sleep 2'
/home/me/script.sh pwd is /tmp
/home/me/script.sh pwd is /tmp
... shows script.sh executing from the parent shell's $PWD.
Since repeat
can't parse a command list, it can't be done. I wish that csh man
could say it plainly like this:
repeat count command
The specified command must be a simple command, (not a pipeline, not a
command list, nor a parenthesized command list), and is executed count
times. I/O redirections occur exactly once, even if count is 0.
Note the single redirection limit, which makes using a while
loop workaround impractical. Example, which doesn't print 9 lives:
echo lives | repeat 9 cat | wc -l
1
Source: the actual quote of man csh
, (but read the entry on repeat
first, then the if
entry), is a bit roundabout:
COLUMNS=90 man csh | egrep -A 7 ' (repeat|if).*and$' | sed -n '1,13{s/^ \{10\}//p}'
if (expr) command
If the specified expression evaluates to true, then the single
command with arguments is executed. Variable substitution on
command happens early, at the same time it does for the rest of the
if command. command must be a simple command, not a pipeline, a
command list, or a parenthesized command list. Input/output redi‐
rection occurs even if expr is false, i.e., when command is not exe‐
cuted (this is a bug).
repeat count command
The specified command, which is subject to the same restrictions as
the command in the one line if statement above, is executed count
times. I/O redirections occur exactly once, even if count is 0.
watch ./dumpstatus
watch
isn't the same as the Linuxprocps
watch
: watch -- snoop on another tty line, but for what I can find, it should be available ascmdwatch
orgnu-watch
.