http://qs1969.pair.com?node_id=714491

The Hindmost has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I'm currently modifying the Linux connection shell script for my University's network (to improve efficiency and connection success) and have found an interesting conundrum: bash works fine as a shell, sh doesn't (no known data for other shells yet).

So I've written a small perl program to pull the current shell out of env's output and warn the user if they're not running bash (code below):

#!/usr/bin/perl -w # shellGet.pl # A program to return the current shell of the user # # Christopher Dykes (2008-09-30) #Use the following modules: use strict; #Use strict syntax use warnings; #Enable warnings #Get the environment data write it externally and open it for use: system("env > .env.txt"); open(ENV, ".env.txt") || die("Couldn't open environment data file: $!" +); while(my $fileLine = <ENV>) #Read in our environment fi +le { if($fileLine =~ /SHELL=/) #Search for the shell line { my @shellLine = split(/=/, $fileLine); #Extract the relevan +t portion print "$shellLine[1]"; #Display our shell #All done: close ENV; #Close the environment file system("rm .env.txt > /dev/null"); #Clean up the environmen +t file exit; #And Quit } } #We shouldn't get here unless there's been an error: die("\aError: Couldn't find SHELL\texiting\n");

This works, but it's more a question of efficiency is this the fastest way to do this (unlikely) and if there is a faster way can you give me any hints.

Thanks in advance Chris

Replies are listed 'Best First'.
Re: Environment discovery under Linux
by plobsing (Friar) on Sep 30, 2008 at 07:57 UTC
    Lookup %ENV in perlvar

    Also note: what you're doing doesn't always work:
    bash-3.2$ echo $SHELL /bin/bash bash-3.2$ dash $ echo $SHELL /bin/bash $ exit bash-3.2$
      You can even link to the documentation of %ENV directly: [doc://%ENV] -> %ENV.
        I never knew that.

        Thanks, and ++, moritz

      Thanks, that'll save a lot of time
      /me rushes of to make modifications
Re: Environment discovery under Linux
by rovf (Priest) on Sep 30, 2008 at 08:06 UTC

    You do not need to run env externally, because the whole environment is already available in the hash %ENV. There is, however, another flaw in your solution: bash does NOT guarantee that SHELL is set at all.

    I don't think there is a foolproof way to find out which shell you have. One possibility to test for bash would be with the following command:

    perl -wle '@ARGV==0 && print "warning, you are not running bash"' $BAS +H_VERSION
    We can't use %ENV here, because BASH_VERSION is not an environment variable.

    Another possibility is to use the current process id ($$) and the output of ps and see how the current process was called, assuming that if it is something like 'bash' or '-bash', it is probably a bash shell.

    -- 
    Ronald Fischer <ynnor@mm.st>
      I feel very foolish for not remembering that;
      (I suppose it's what you get for getting an idea on a Uni pub crawl scrawling it on a beer mat and trying to code it up when you get in still drunk; oh well)
Re: Environment discovery under Linux
by Corion (Patriarch) on Sep 30, 2008 at 08:03 UTC
Re: Environment discovery under Linux
by lamp (Chaplain) on Sep 30, 2008 at 08:08 UTC
    Use $ENV{SHELL} in Linux/Unix and $ENV{COMSPEC} in DOS/Windows.
Re: Environment discovery under Linux
by JavaFan (Canon) on Sep 30, 2008 at 09:41 UTC
    Not all shells set SHELL, and even in bash, SHELL isn't readonly. If I run for instance 'tcsh' from bash, SHELL will still say "/bin/bash" because tcsh doesn't set SHELL.

    But I don't understand why it matters what shell the user is running when calling your script. If the script starts with

    #!/bin/bash
    then the script will be run by bash, unless explicitly run by another shell. In that case, don't do it.

    Note also that you can get a users login shell by just checking the result of getpwnam().

Re: Environment discovery under Linux
by toolic (Bishop) on Sep 30, 2008 at 13:17 UTC
    In addition to the advice already provided, it is generally not necessary to create a temporary output file when running a command out to the shell. Instead of running the command via system, it is simpler to just collect the command's output in an array using qx:
    my @lines = qx(env);
Re: Environment discovery under Linux
by Wiggins (Hermit) on Sep 30, 2008 at 13:46 UTC
    In my experience, there are also situations where 'sh' is a "link to" or a "renameing of" 'bash'.

    The fundamental problem is determining if whatever is the default shell; will it execute your problematic shell commands. First running a small test shell script designed to use the problematic statements alone, as a test.

    If that works , regardless of what the shell is called, then your production shell will run as well.

Re: Environment discovery under Linux
by gloryhack (Deacon) on Sep 30, 2008 at 17:05 UTC
    Although I've not seen the shell script in question, I'm curious to know if it might be more efficient to simply eliminate the bashisms within it and thus avoid all of this hoop-jumping.
Re: Environment discovery under Linux
by graff (Chancellor) on Oct 01, 2008 at 04:46 UTC
    Um... If you are talking about users on a network of linux machines, and determining what shell gets invoked when people login or otherwise connect, wouldn't you just look at the entry for the given user in /etc/passwd? That is what sets the login shell.

    If it's a matter of warning users about the risks starting up other shells after they are logged in/connected, that should be in the text of "/etc/motd" ("message-of-the-day"), which gets displayed at login (before the initial shell prompt). But as for controlling shell behavior at login, /etc/passwd handles that.

    (Or maybe I'm completely missing the point about your question...)