Backgrounding shell with delay

I am having a brain freeze. How can I background the first command so the beep command is executed first ?

do shell script "sleep 5 ; open '/Users/jd/Desktop/test.txt' > /dev/null 2> /dev/null &"
beep 2

Hi,

I don’t really know what ‘wait’ does, but does this work:

set the_list to (do shell script “wait; ls ~/”)
beep 3
the_list

editted: it doesn’t work. Just experimenting.:slight_smile:

editted: this seems to work:


set the_list to (do shell script "ls -R ~/; wait")
beep 3
the_list

gl,

You could put the beep before the shell script, of course. :wink:

But otherwise, parenthesising the two shell commands seems to work:

do shell script "(sleep 5 ; open '/Users/jd/Desktop/test.txt) > /dev/null 2> /dev/null &"
beep 2

And who says that AppleScript isn’t intuitive … it even executes from top to bottom :wink: Your other suggestions works too. Thank you.

:slight_smile:

I see someone has made the same observation as I did.

Well, I just wanted to comment on the use of redirection, by another observation I have done, that at least helped me to visualize what is going on, which sometimes was confusing, until I understood the crux of the matter.

Filehandles are values, and not refereces (or addresses), so, that is why order matter!

If you specify redirection like: mycommand >out 2>&1, then standard output are made to be redirecte to out, and that redirection are then copied over to standard errors (2) handle.

This may not be so clear, but if you do it the other way around, it should be clearer: mycommand 2>&1 >out, will make standard error be redirected to standard out, which goes to the console (/dev/tty), standard out is then redirected to the file out, but standard error will still point to the previous value of standard out which was /dev/tty.

I hope this makes it clear to anybody unsure that it is values of filehandles that are copied, and not an address, which would have make stderr automatically point to out as well.

The third observation in this post is that in order to make sending a shell script into background by using the ampersand operator &, you really have to redirect standard output, and maybe standard error to something else, than the logical “terminal”, so that the do shell script , sense that there is no output to get here, and hence doesn’t “hang” in the script waiting for it.

command >/dev/null 2>/dev/null &

is indeed the same as:

command >/dev/null 2>&1 &

But it can be written shorter as:

command &>/dev/null &

&> is redirection for both stdout and stderr

Thanks DJ.

You’re welcome!

One more thing:

McUsr mentioned /dev/tty as the standard output, that only goes for pseudo terminals like the Terminal.app. Do shell scripts are directly connected to 3 other files
0 = /dev/stdin
1 = /dev/stdout
2 = /dev/stderr

echo 'hello world!'

is the same as:

echo 'hello world!' 1>/dev/stdout 2>/dev/stderr

This can let you control the output of an series of commands better. For instance you can redirect the output to another file and back to stdout or stderr again. For do shell script commands the following rule applies. When an script exits 0 (zero) then the contents of /dev/stdout is returned. When the command exit with
an non-zero value the contents of /dev/stderr is used as the error message. Here an example to create your own error:

echo 'hello world!' >/dev/stderr; exit 1

or shorter:

echo 'hello world!' >&2; exit 1

To be totally correct, stdin == 0, stdout ==1 and stderr == 2. The other thing is, that when you execute commands from a terminal, then the three handlers are always redirect to the logical device /dev/tty, which in turn may be redirected to a pseudo terminal like /dev/ttys009 for instance.

It is quite common to use redicrection, with the exec call, so that you for instance can close stdin temporarily, and reopen it to /dev/tty directly, to ensure that you get input from the keyboard, and then reopen it again.

Below is a shell script that only demands one keypress for y or n.

[code]#! /bin/bash

### CMD Returns exitcode upon pressing y or n or q, “keypress” read code. !#

Traps ^C to keep our terminal sane under all conditions. Q - quits.

Conventions:

Under no circumstanses will the user have the possibiltiy to interrupt us by pressing ^C

Pressing ^Z on the other hand, is really a feature should the user want to inspect something

before he answer.

Then it is nice to see the previous question again after she presumably have

inspected what she was to do with the item in question.

This is the convention. Its easy to add features like All, by adding some functionality.

trap ‘’ SIGTSTP

trap - SIGTSTP

prgname=yesno
version=“1.0”
Usage=“Usage : $prgname [-huv; --help, --usage, --version ]”

version()
{
echo $prgname" : “$version”
Copyright 2008 (c) McUsr
Is put in the public domain under the GNU Gpl 2.0 license.
No warranties about what so ever are given about what so ever

  • to the extent permitted by law.
    $prgname Needs the Bash commandline interpreter in order to work."

}

phelp()
{
echo "
$Usage
$prgname : filters the keyboard for the keypresses: [yY] [nN] [qQ] and returns a corresponding
exitcode
lets Suspend interrupts (^Z) fall through and gives an unique returncode when awakes again.
Read the manpage (yesno.1) or read the program code ($0) for information.
INTENT
$prgname : Enables swift responses from the user to the utility, and gives the caller an
opportunity to rerun any questions if the calling process was suspended. Like if the user has
suspended the program to find out if it is really sound to overwrite that file after all.
" 1>&2
}

myhandler()
{
trap ‘’ SIGCONT
echo “interrupted!!!”
exit 101
}
if [ $# -gt 0 ] ; then
if [ $# = 1 ] ; then
if [ “$1” = “-u” -o “$1” = “-h” -o “$1” = “–help” -o “$1” = “–usage” ] ; then
phelp ; exit
elif [ “$1” = “-v” -o “$1” = “–version” ] ; then
version ; exit
else
echo "Bad option $1 " 1>&2
echo $Usage 1>&2
exit
fi
else
echo "Bad nr of arguments " 1>&2
echo $Usage 1>&2
exit
fi
fi
trap ‘’ SIGINT
trap myhandler SIGCONT
while true; do {

ehco here

read -n 1 -s MYCHAR </dev/tty
case "$MYCHAR" in
([yY])
	 exit 0 ;;
([nN])
	 exit 1 ;;
([qQ])
	 exit 99 ;;
esac

} done[/code]
It is to be used in a shell script like pick, below which you use to execute shell scripts interactively:
USAGE:

cat `pick *`

[code]#! /bin/bash

$Log: pick,v $

Revision 1.4

### pick: select arguments

declare ret

echo $0" cmdln : $* >/dev/tty

echo “Hit Y(es), N(o) or Q(uit)” >/dev/tty

for i # for each argument
do
echo -n " “$(echo $i |sed -n ‘s/[ ]*$//p’)”:(y/n/q)?" >/dev/tty
yesno
if ret=$? ; [ $ret -eq 0 ] ; then
echo “$i”
echo " – Yes" >/dev/tty
elif [ $ret -eq 99 ] ; then
echo " – Quit" >/dev/tty
break
else
echo " – No" >/dev/tty
fi
done </dev/tty[/code]
I recommend reading a good book, like “The Unix Programming Environment” :).

We’re both wrong :confused: I corrected my post above. File descriptor 3 on Mac OS X has no meaning but some systems do. Like an system log.

Hello.

I actually meant 2 not 3, I mistyped.

The log on descriptor 3, I haven’t checked that, that would sound a whole lot easier than using the syslog facility. :slight_smile:

Actually, the times I have checked the handle nr I get when I open a file in a C-program, (the first file-handle) it gets nr 4.

Edit

I read a little about it here, and my understanding of why it is so, that nr 4 is the first you get, is that it may not necessarily be open for writing to a log, but that it is reserved for syslog to bind to 0.0.0.0:214 for logging. And that you should really call syslog for opening and closing the log.

This implies that you can’t use filedescriptor 3 in bash for logging. :frowning:

On Mac OS X the file descriptor 3 is just the first available file descriptor when you open an file… tested with the following C code:

[code]#include <stdio.h>

int main (int argc, char * argv[])
{
FILE *fp;

fp = fopen(“/Users//Dekstop/testfile.txt”, “r”);

if (fp == NULL){
printf(“cannot open the requested file\n”);
return 1;
}

printf(“The first available file descriptor is %i\n”, fp->_file);
return 0;
}[/code]
it returns 3 on my machine as proof that Mac OS X like many systems that file descriptor 3 is the first avaialble file descriptor and not an special one like on some systems; not 4.

Hello.

I guess that can depend on whether you have syslogging enabled. :slight_smile:

I have, so the first free I get is nr 4.

But that doesn’t make it in special file descriptor :slight_smile: . Just the first available file descriptor is in use by syslog, which is not 4

. printf("The first available file descriptor is %i and I must not forget to close the opened file after using it", fp->_file);
:wink:

It is maybe not so special, but the filedescriptor is grabbed globally, which is interesting, that is, you can’t have a file with that number in any process. You know , you have 0,1 and 2 in any terminal window, that is not the case with file descriptor nr 3 when the syslog daemon is running.

:smiley: I knew someone would bring that up. in my defense I don’t close files here, because when the process is finished the file is close by the kernel. But you’re right that it is cleaner to do it yourself.

First of all an file descriptor is locally. File descriptors are foreach process starting at 0 where the first 3 is assigned by the kernel when the process comes alive. The syslog file descriptor is requested by the process and the kernel returns file descriptor 3 as the 4th open file by your process. Here’s an example of my point:

#! /bin/sh exec 3<&0 exec 0< $FILE while read line do echo $line done exec 0<&3
With this code I set stdin temporarily to file descriptor 3, and set another file to stdin. Then wen done processing I can set stdin back again. Using file descriptor 3 here has no problem at all. Also the C example gives my file descriptor 3, how should I be able to block this? According to the manual of syslog(3) it doesn’t need to be file descriptor 3 at all. It says it may open an file descriptor.

Hello.

Well, all shells are forked from the init process, if the init process, which is a daeomon too, has been informed that descriptor nr 3 isn’t available, then maybe the kernel has been set up, so it starts forking out file descriptors from nr 4 because nr 3 is taken. By reading the post earlier from Stack overflow, I really sensed that syslog is dedicated to nr #3, it also seemed like the guys dealing with it had read the source, since they were able to mention descriptor nr 3, and even that it was bound to 0.0.0.0:214.

So I guess I would get something that returns EBADACCESS or something, if I try to run that snippet. ( I didn’t get that of course, since that is an error from stdc, but I got “ambiouous redirect”, when I ran it.

I’ve read the post on StackOverflow as well. Nobody mentioned that there where issues with file desciptor 3. Only the TS just asks because he thought there was an problem. His assumptions doesn’t make it true, he’s shooting in the dark. Because the first file is opened by syslog(), obviously it will file be descriptor 3. As on Mac OS X as on Linux it doesn’t matter which file descriptor syslog use as long as the file descriptor points to the right socket that will be used to send messaged to syslogd. Syslog is just an library with an process as you would connect to mysqld from your mysql library (locally), no magic here.

Hello.

No Magic Here… now that is a good thing! I am glad there isn’t any need for LInux Magic here. :slight_smile:

The first open file descriptor, maybe it is so, but I am not sure, to know for sure I would either have too look into the source, or load/make another daemon, that keeps a file descriptor open at all times, and see what happens, if I load that one before the syslog one. And then I’m not sure if I can totally manage the same, as you can have a file descriptor 3 in two terminal windows at the same time, (that is the special part). I think at least syslog has taken some measures to make its filedescriptor, the only one with that number.

The idea in that post, was the same as how this started, avoid sockets via syslog calls, and write to syslog’s open file directly instead. :slight_smile: