LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This 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


Reply
  Search this Thread
Old 05-19-2021, 05:53 PM   #1
mfoley
Senior Member
 
Registered: Oct 2008
Location: Columbus, Ohio USA
Distribution: Slackware
Posts: 2,628

Rep: Reputation: 180Reputation: 180
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:
Code:
echo $- >/tmp/inter
That gives "hB", no "i".

So, how do I do this?

Last edited by mfoley; 05-19-2021 at 05:54 PM.
 
Old 05-19-2021, 07:01 PM   #2
dannybpng
Member
 
Registered: Sep 2003
Location: USA
Distribution: Fedora 35
Posts: 79

Rep: Reputation: 22
This should do the trick. The -t option checks if the given file descriptor number is a terminal.

Quote:
if [ -t 0 ];then
echo Interactive
fi
 
Old 05-20-2021, 01:35 AM   #3
mfoley
Senior Member
 
Registered: Oct 2008
Location: Columbus, Ohio USA
Distribution: Slackware
Posts: 2,628

Original Poster
Rep: Reputation: 180Reputation: 180
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.

Last edited by mfoley; 05-20-2021 at 01:43 AM.
 
Old 05-20-2021, 02:32 AM   #4
shruggy
Senior Member
 
Registered: Mar 2020
Posts: 3,686

Rep: Reputation: Disabled
Quote:
Originally Posted by mfoley View Post
The bash script I put the test line in is getting stdin piped into it! That's why it comes back "not interactive".
Then test for 1 (stdout) or 2 (stderr).
 
1 members found this post helpful.
Old 05-20-2021, 03:31 AM   #5
Reuti
Senior Member
 
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 15.2
Posts: 1,339

Rep: Reputation: 260Reputation: 260Reputation: 260
Look at the name of the parent process.

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).
 
Old 05-20-2021, 04:09 AM   #6
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,836

Rep: Reputation: 1221Reputation: 1221Reputation: 1221Reputation: 1221Reputation: 1221Reputation: 1221Reputation: 1221Reputation: 1221Reputation: 1221
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
 
Old 05-20-2021, 07:02 AM   #7
dannybpng
Member
 
Registered: Sep 2003
Location: USA
Distribution: Fedora 35
Posts: 79

Rep: Reputation: 22
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
 
Old 05-20-2021, 08:48 AM   #8
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Rep: Reputation: 448Reputation: 448Reputation: 448Reputation: 448Reputation: 448
In default ~/.bashrc there is this:

Code:
# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac
It checks if $- contains an i or not.
 
Old 05-20-2021, 09:16 AM   #9
mfoley
Senior Member
 
Registered: Oct 2008
Location: Columbus, Ohio USA
Distribution: Slackware
Posts: 2,628

Original Poster
Rep: Reputation: 180Reputation: 180
Quote:
Originally Posted by shruggy View Post
Then test for 1 (stdout) or 2 (stderr).
Yes! When piping into a script:
Code:
cat thisfile | testme
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 View Post
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 View Post
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 View Post
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.

I'll experiment more with test -t 2.
 
Old 05-20-2021, 09:36 AM   #10
shruggy
Senior Member
 
Registered: Mar 2020
Posts: 3,686

Rep: Reputation: Disabled
You can try all of them and see whichever works:
Code:
#!/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
 
1 members found this post helpful.
Old 05-20-2021, 11:46 AM   #11
mfoley
Senior Member
 
Registered: Oct 2008
Location: Columbus, Ohio USA
Distribution: Slackware
Posts: 2,628

Original Poster
Rep: Reputation: 180Reputation: 180
I think the -t 2 solution will work for me. I'm going to mark that as the solution. I had no idea this would be so difficult!
 
  


Reply

Tags
bash



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
LXer: What is the difference between Non-Login and Login, Non-Interactive and Interactive shell sessions in Linux/Ubuntu/Debian LXer Syndicated Linux News 0 01-17-2020 08:31 AM
[SOLVED] Silencing the line "echo test > test/test.txt" in a shell script Arenlor Linux - General 2 06-18-2010 01:37 PM
Interactive and non-interactive shells? Tim356 Linux - Newbie 7 11-05-2008 10:32 PM
BASH - How to open an interactive script from a non interactive script..... OldGaf Programming 4 06-29-2008 04:34 PM
interactive and non-interactive shell linuxjamil Programming 3 09-03-2006 08:42 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 12:15 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration