Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Recognizing an interactive shell 2

Status
Not open for further replies.

Daedelus

Technical User
Aug 14, 2002
70
US
What is the best way to determine in a shell whether it is being run interactively or is running a script?

The problem is most workers in my group need to do their work in a common directory. The usual practice has been to add 'cd /workingdirectory' line to their .kshrc files (obviously we usually work in ksh), so that when they log in, they are where they want to be.

This causes problems with scripts that need to be run in other directories, however. Any script that is "shebanged" will automatically switch to the workingdirectory when it is started up. (Not shebanging of course runs the risk that the user is working in an uncompatible shell.)

One solution is to change the .kshrc file lines to something like
[[ $0 = /usr/bin/ksh ]] && cd /workingdirectory

If the default shell is /usr/bin/ksh, then the cd will be executed only for interactive shells. But this requires that the user must stick with this shell. I could figure out which shells use the .kshrc file and test for them all, but I was wondering if there was a better way of determining that the current shell is interactive, rather than running a script.
 
I wouldn't 'shebang' the script then. If there are common components within your .profile(s) that your scripts reference, they should be taken out and placed somewhere else or the other solution is to write all of your scripts with absolute path which is a good practice anyway.

Just my 2 cents.
 
Maybe put the cd in .profile (invoked once at login) instead of .kshrc (invoked each time a shell is started).

And to test if a script is running interactively:-

if $(tty -s)
then
echo interactive
fi



 
if you're a csh, $?prompt
if you're in any other shell ${PS1:+1}

check for =1 :)
 
As I said, not "shebanging" the scripts runs the risk of someone trying to run them under an incompatible shell (for instance the c shell, since they were all written for korn). This is perhaps a moot point, since few others here are even aware that there is a choice. Currently none of the scripts are shebanged. But I thought it would be wise to introduce the practice of shebanging if possible, since it makes the scripts more universally applicable. Most of these scripts are used for manipulating data files in whatever directory the worker is currently using. They would not be happy at the idea of having to specify the full path to whatever file they are working on, which is the only way that I could get the scripts to only use absolute paths.
--------------------
"Maybe put the cd in .profile (invoked once at login) instead of .kshrc (invoked each time a shell is started).

And to test if a script is running interactively:-

if $(tty -s)
then
echo interactive
fi
"
--------------------
I'll look into the .profile bit - I've never bothered to learn the difference between the handling of the .profile and .kshrc files under the Korn shell, since until now I haven't come across anything that .kshrc wasn't good for.

The tty -s won't work for what I am looking for. Perhaps I should of worded it better. I want to determine if the shell that is executing the .kshrc file is running a script or if it is an interactive shell. The tty -s command only tells me whether or not standard input is from the terminal. This is the case for most of the scripts as well as for interactive shells.
--------------------
"if you're a csh, $?prompt
if you're in any other shell ${PS1:+1}

check for =1 :)"
--------------------
Sorry, but that does not work - at least not on this system. PS1 is defined even when the shell is running a script. (I don't know if this is true in general - the local system is set up so that PS1=`hostname`':$PWD>'. It may be that this is why PS1 is always defined for us, even for scripts.)

Regardless, thanks for all of your suggestions!

 
Try this:
Code:
case "$-" in
*i*) echo $0 is Interactive;;
*) echo $0 is running in a subshell;;
esac

Hope This Help
PH.
 
That's what I was looking for! Thanks! None of my references mentions "i" as a possible value for $-. They all took the lazy way out - saying that $- is the options given in the last "set" command (or shell call). But these commands do not list "i" as an option (for obvious reasons).

This is even more handy, as I haven't been able to get the .profile bit to work for me. (I suspect that this is again a result of how this system has been set up. When I log out and back in again I find that my .profile file has been deleted!)

Thanks again to everyone for responding.
 
From the ksh man page...


Invocation
If the shell is invoked by exec(2), and the first character
of argument zero ($0) is -, then the shell is assumed to be
a login shell and commands are read from /etc/profile and
then from either .profile in the current directory or
$HOME/.profile, if either file exists. Next, commands are
read from the file named by performing parameter substitu-
tion on the value of the environment variable ENV if the file exists. If the -s flag is not present and arg is, then
a path search is performed on the first arg to determine the
name of the script to execute. The script arg must have read
permission and any setuid and setgid settings will be
ignored. If the script is not found on the path, arg is
processed as if it named a builtin command or function. Com-
mands are then read as described below; the following flags
are interpreted by the shell when it is invoked:

-c Read commands from the command_string operand. Set
the value of special parameter 0 from the value of the
command_name operand and the positional parameters
($1, $2, and so on) in sequence from the remaining arg
operands. No commands will be read from the standard
input.

-s If the -s flag is present or if no arguments remain,
commands are read from the standard input. Shell out-
put, except for the output of the Special Commands
listed above, is written to file descriptor 2.

-i If the -i flag is present or if the shell input and
output are attached to a terminal (as told by
ioctl(2)), then this shell is interactive. In this
case, TERM is ignored (so that kill 0 does not kill an
interactive shell) and INTR is caught and ignored (so
that wait is interruptible). In all cases, QUIT is
ignored by the shell.

-r If the -r flag is present the shell is a restricted
shell.

The remaining flags and arguments are described under the
set command above.
 
Thanks. I was looking only at "set" when I should have been looking at "ksh".

As an aside, the reason .profile will not work for me is that the /etc/profile script has been set up to delete any .profile files in the user's home directory, except for a few privileged users. (This is also where the deviant PS1 is defined.)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top