in reply to How do I test if my Perl script was run using a login vs a non-login shell

Why do you care if it's a login or non-login shell? Perhaps you really want to know if the script is being run interactively?

Detecting interactive/non-interactive shell

  • Comment on Re: How do I test if my Perl script was run using a login vs a non-login shell

Replies are listed 'Best First'.
Re^2: How do I test if my Perl script was run using a login vs a non-login shell
by paulski82 (Novice) on May 24, 2012 at 01:40 UTC

    I actually want to know both these things since shells behave differently based on whether they are login or non-login, and/or interactive, non-interactive. See the following from the bash man page for an example (bash 3.2):

    When bash is invoked as an interactive login shell, or as a non +-interactive shell with the --login option, it first reads and execu +tes commands from the file /etc/profile, if that file exists. A +fter reading that file, it looks for ~/.bash_profile, ~/.bash_login, +and ~/.profile, in that order, and reads and executes commands from + the first one that exists and is readable. The --noprofile option +may be used when the shell is started to inhibit this behavior. When a login shell exits, bash reads and executes comman +ds from the files ~/.bash_logout and /etc/bash.bash_logout, if the fi +les exists. When an interactive shell that is not a login shell is started, + bash reads and executes commands from ~/.bashrc, if that file exis +ts. This may be inhibited by using the --norc option. The --r +cfile file option will force bash to read and execute commands from f +ile instead of ~/.bashrc. When bash is started non-interactively, to run a shell script, +for example, it looks for the variable BASH_ENV in the environme +nt, expands its value if it appears there, and uses the expanded +value as the name of a file to read and execute. Bash behaves as if +the following command were executed: if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi but the value of the PATH variable is not used to search for th +e file name.

    So your link is useful for solving the interactive, non-interactive part of the puzzle, but I'm still keen to know how to solve the login/non-login part of the puzzle.

    Thanks for the link.

      Here's a solution I came up with in case it helps someone else:
      my $p; my login_shell = 0; # NOTE: PERL ARGV[0] does not supply the '-' suffix like in # C, which would allow us to do a reliable test to check if # we are running inside a login shell. So we need to guess # this using some hacks. # HACK 1 # This is a hack to guess whether we are an interactive # shell in an SSH session based on the SSH_TTY environment # variable being set or not. # NOTE: If people are accessing the system via other # mechanisms like telnet etc. this won't catch those cases. # NOTE: OpenSSH's sshd will prefix shell with '-' for # interactive shells but not for non-interactive shells # e.g. shells called using -c <command>. # For the gory details see: # session.c:void do_child(Session *, const char *); if ($ENV{'SSH_TTY'}) { $login_shell = 1; } # End if. # HACK 2 # This is a hack to check whether this shell was called via # su and the shell was a login shell. Get the PID of the # parent process of current instance of this process. my $parent_pid = getppid(); } # Get the executable and args of the parent process. my $process = ""; my $command = "/bin/ps -eo pid,args"; open(FP, "$command|") || die("$!\n"); while (my $proc_line = <FP>) { chomp($proc_line); $proc_line =~ s/^\s+//g; $proc_line =~ s/\s+$//g; my ($pid, $cmd, @list) = split(/\s+/, $proc_line); $cmd = (($p = rindex( $cmd, '/' )) >= 0) ? substr($cmd, $p + 1) : $cmd; my $args = ''; foreach (@list) { $args .= "$_ "; } $args =~ s/\s+$//g; if ($pid eq $parent_pid) { $process = "$cmd $args"; chomp($process); last; } } close(FP); # If the parent process was an su command with a login # shell, then this shell should be a login shell too. if ($process =~ /^su /) { if (($process =~ / - /) or ($process =~ / -[A-z]*l[A-z]* /) or ($process =~ / --login /)) { $login_shell = 1; } }