comamnds running interactively, failed in script wrigint

Hi all,
I am trying to run these commands in shell script, but there seem to be some mistake. Somehow it is not accepting the last important comamnd "eval `scram runtime -sh`". However, when I try them interactively, it works all fine.

[pooja04@cmslpc07 v6]$ SOURCEPATH=/uscms_data/d3/pooja04/CMSSW_5_3_3_patch2/src/ElectroWeakAnalysis/MultiBosons/test/
[pooja04@cmslpc07 v6]$ cd $SOURCEPATH
[pooja04@cmslpc07 test]$  eval `scram runtime -sh`

SCRIPT

SOURCEPATH=/uscms_data/d3/pooja04/CMSSW_5_3_3_patch2/src/ElectroWeakAnalysis/MultiBosons/test/

SetEnv () {
    SCRIPT=`readlink -f $0`

    SCRIPTPATH=`dirname $SCRIPT`
    cd $SOURCEPATH
    echo  $SOURCEPATH
    eval `scram runtime -sh`
    cd $SCRIPTPATH
}

any piece of hint is appreciable.

Thanks

You cannot depend on $0. It may be an absolute path, relative path, or no path depending on how the program is run.

hi corona,
I did not understand. I have tested that piece of code. It just cd in the current working directory.

What's the output of scram runtime -sh ? Is it different in the script or from the command line?

Hi RudiC,
I have to execute it to set the correct working environment. A simple test to check it its working is following

SOURCE=/uscms_data/d3/pooja04/CMSSW_5_3_3_patch2/src/ElectroWeakAnalysis/MultiBosons/test/
[cmslpc@test]$ cd $SOURCEPATH
[cmslpc@test]$ eval `scram runtime -sh`
[cmslpc@test]$ root -l 
root [0] 

So after execution of that command, it recognize the ROOT.

While with my script, it give the following message:

script.sh

#!/bin/bash                                                                                                                                           
date

SOURCE=/uscms_data/d3/pooja04/CMSSW_5_3_3_patch2/src/ElectroWeakAnalysis/MultiBosons/test/

SetEnv () {
    SCRIPT=`readlink -f $0`
    SCRIPTPATH=`dirname $SCRIPT`
    cd $SOURCEPATH
    echo  $SOURCEPATH
    eval `scram runtime -sh`
    cd $SCRIPTPATH
}

if  [ "$1" = "setenv" ]; then
    SetEnv
    exit 0
fi

Execution:

[cmslpc@test]$ ./script.sh  setenv
Tue Sep 25 15:21:48 CDT 2012
/uscms_data/d3/pooja04/CMSSW_5_3_3_patch2/src/ElectroWeakAnalysis/MultiBosons/test/
[cmslpc@test]$ root -l
-bash: root: command not found
[cmslpc@test]$ 

Thanks,

You've tested it in your home dir, by running it in a manner where $0 can be depended on.

Except, you can't depend on $0. When something that's not you runs it, especially automatic things like cron and so forth, you have no idea what your current dir, and the contents of $0, are going to be. It might start in / with a useless $0 like -bash or something. Or it might give an absolute path you weren't expecting. etc. I keep telling people not to do this but until it breaks down like this, they never understand why.

Try typing echo $0 into your shell for example. I get -bash . That's not any sort of directory.

I just tested that piece of code as script like this [1] and the output is [2] just as I want it to be.
It take me back to my working directory.

[1]

SetEnv () {
    SCRIPT=`readlink -f $0`
    echo $SCRIPT
    SCRIPTPATH=`dirname $SCRIPT`
    cd $SOURCEPATH
    echo  $SOURCEPATH
    eval `scram runtime -sh`
    cd $SCRIPTPATH
    echo $SCRIPTPATH
}

[2]

[pooja04@cmslpc17 v6]$ ./script.sh  setenv
Tue Sep 25 15:33:30 CDT 2012
/uscms/home/pooja04/script/AnalysisCode/Code42012/v6/Script4JobSubmit.sh
/uscms_data/d3/pooja04/CMSSW_5_3_3_patch2/src/ElectroWeakAnalysis/MultiBosons/test/
/uscms/home/pooja04/script/AnalysisCode/Code42012/v6
[pooja04@cmslpc17 v6]$ 

$0 does not mean "path to my program". That's what it traditionally is, and it's what you get whenever a shell runs a program, but when something that's not a shell runs your program, that's not guaranteed by any means. cron will give weird values for $0. CGI gives weird values for $0. And so forth.

So yes... It does when you run it, from a terminal, giving it an absolute path. When things other than you run it, from non-terminals, in ways and from places you never did, you might get something else.

These two C programs show how it works:

$ cat printzero.c

#include <stdio.h>

int main(int argc, char *argv[])
{
        printf("$0 is %s\n", argv[0]);
}

$ cat zero.c

#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        if(argc < 2)
        {
                fprintf(stderr, "usage:  ./zero program zeroth-argument\n");
                return(1);
        }

        // First argument is the program name and path.  Second is $0.
        // Note that NOTHING forces them to be the same.
        execl(argv[1], argv[2], NULL);
        return(1);
}

$ gcc zero.c -o zero
$ gcc printzero.c -o printzero
$ ./printzero

$0 is ./printzero

$ ./zero ./printzero slartibartfast

$0 is slartibartfast

$

So, when you run ./printzero by itself, the shell runs it, and $0 is what you expect.

When the zero program runs printzero, it can give whatever weird and wild value it wants to $0, and does.

Some shells will make a halfhearted attempt to correct the value of $0 into something 'useful', but they're not psychic. They can't recover paths they were never given in the first place.

So $0 is only what the program calling it says it is. It's not necessarily the information you want. Do not depend on it if you want your scripts to be run by cron and the like.

Ohh,
Thanks for the explanation.
just wondering...can I rely this $0 while working with shell script probably?
If not, then what could be the other way to write it in shell script.
BTW, Google helped me in finding that $0 :smiley:


checking the current dir
go to other dir
execute something there
come back to previous directory

Thanks

Only if you know for a fact it's going to be launched from a shell and not by cron or anything.

Either code the path into the script, take it as a parameter, or make it something you can grab by sourcing /etc/profile. That's what it's for, really -- storing global values like that.

Most programs don't keep their data in the same location as the executable, you know, especially if they need to write to it. Writing to the same folder your program exists in could be a recipe for disaster if your program goes wrong -- might delete itself, rename itself, truncate itself, overwrite itself, etc, or be manipulated into doing so by clever/malicious people.

I used to do it.. But every time I used to make different directory and cp the content..I always used to forget to change this variable..and I really had hard time dealing with the consequences..:frowning:

So I prefer taking out some time and do Google about the solution..
Also sombeody was suggesting me that $pwd serve the purpose in shell script. I did not find anything on google related with this.

Thanks,

So put more error-checking in your code. Check for the presence of certain files. If they're not there,complain that such-and-such variable hasn't been set and quit.

#!/bin/bash

die() {
        echo -- "$@" >&2
        exit 1
}

. /etc/profile

[ -z "$MYDIRVAR" ] && die "MYDIRVAR not set in /etc/profile"
[ -e "$MYDIRVAR" ] || die "MYDIRVAR=$MYDIRVAR does not exist"
[ -d "$MYDIRVAR" ] || die "MYDIRVAR=$MYDIRVAR is not a directory"
[ -f "$MYDIRVAR"/myscript.sh ] || die "MYDIRVAR=$MYDIRVAR does not contain myscript.sh"

echo "MYDIRVAR=$MYDIRVAR, folder exists and contains myscript.sh, ready to go" >&2

pwd is your shell's working directory.

Things like cron or CGI scripts and so forth, which don't actually login as you, are likely to have a $pwd of / .

1 Like

Cool..nice deBugging..:b:
So if I assume this part to be solved. The question remains that the script failed to execute a simple line of command..why..?? No idea !!

Things like cron, cgi-scripts, and so forth also have a pretty minimal $PATH. It probably couldn't find scram. In short, everything local to your shell login that you've been depending on when you write your scripts, can't be depended on if you're not doing a shell login.

You can get a more complete PATH by doing . /etc/profile where such global settings are supposed to be kept. That's done automatically for you on login of course, but for cron and such, not unless you ask for it.

You could also do /absolute/path/to/scram instead.