[SOLVED] How to I test if a script is run from and interactive shell?
Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
How to I test if a script is run from and interactive shell?
I have a script that can be run as a sendmail alias command, or a cron job, or run by a user. I'd like the script to know if it's being run by cron or otherwise in the background versus a user running the command at a bash prompt.
What I've found so far on the web says that if $PS1 exists, it's running from a user command line. However, I created a simple script:
Code:
echo "$PS1" >/tmp/inter
and after running it from the command line /tmp/inter is empty. I've also read that $- will have an "i", so similar script:
dannybpng: Nope, that doesn't work. If I type the following, manually, at the command line:
Code:
if [ -t 0 ]; then echo interactive; else echo not interactive; fi
It comes back with "interactive". If I put that same line in a bash script and run the bash script it comes back "not interactive".
Other ideas?
More info ...
The bash script I put the test line in is getting stdin piped into it! That's why it comes back "not interactive". Yet I'm running it manually, at an ssh terminal session. So I need another way to figure that out.
If this code is put into a script and run from a cron job, it does work. Running this same script from the prompt still means that there is a connection with a terminal. My guess is that it will also work with sendmail, unless the user is directly interacting with the program.
having the line "if [ -t 2 ]; then echo interactive ; else echo not interactive ; fi" it comes back back "interactive". Testing for 0 comes back "not interactive". This may be the solution. I'll experiment more.
Quote:
Originally Posted by Reuti
One could test for the parent of the script in question:
Code:
ps --no-headers -p $PPID -o command
This should output either -bash or something like /usr/sbin/CRON -n (path maybe different on your distribution though).
Interestingly, I get the following results:
-bash when run manually at the command line
-su when run as shown above inside the testme script at the command line
/usr/sbin/crond -l notice when run from crontab
(both lines) when run from crontab
Quote:
Originally Posted by MadeInGermany
The tests in your initial post are okay.
Code:
if [[ $- == *i* ]]; then echo interactive; else echo not interactive; fi
should work in bash/ksh/zsh
Usually testing $PS1 is good enough:
Code:
if [ -n "$PS1" ]; then echo interactive; else echo not interactive; fi
$PS1 is not defined either in the cron case or the piped command line case.
Quote:
Originally Posted by dannybpng
If this code is put into a script and run from a cron job, it does work. Running this same script from the prompt still means that there is a connection with a terminal. My guess is that it will also work with sendmail, unless the user is directly interacting with the program.
Code:
if [ -t 0 ];then echo Interactive; fi
Yes, it comes back "not interactive" when run from cron or sendmail. It comes back "interactive" when run inside a script at the command line if stdin is the keyboard. BUT, as I've said, it comes back "not interactive" if piping into the script.
There are some environment variable differences. the piped-script-command-line has LS_COLORS set. Cron does not. TERM is "linux" for cron and "xterm" for piped/command. cron has CONSOLE set; piped/command does not. There are other, none of which seem satisfactory.
#!/bin/sh
for i in 0:stdin 1:stdout 2:stderr
do [ -t ${i%:*} ] && echo ${i#*:} is terminal
done
Code:
$ ./inter
stdin is terminal
stdout is terminal
stderr is terminal
$ echo|./inter
stdout is terminal
stderr is terminal
$ ./inter|cat
stdin is terminal
stderr is terminal
$ echo|./inter|cat
stderr is terminal
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.