csh script inherit envirionment variables? - solaris

I found an odd problem when I run a simple csh script on Solaris.
#!/bin/csh
echo $LD_LIBRARY_PATH
Let's call this script test. When I run this:
shell> echo $LD_LIBRARY_PATH
shell> /usr/lib:/usr/openwin/lib:/usr/dt/lib:/usr/local/lib:/lib:/my_app/lib
shell> ./test
shell> /usr/lib:/usr/openwin/lib:/usr/dt/lib:/usr/local/lib:/lib
They print out totally different values for $LD_LIBRARY_PATH. I can't figure out why. (It's OK on my linux machine)
Thanks!

Do you set $LD_LIBRARY_PATH in your $HOME/.cshrc?
You really shouldn't if you do, since it often just breaks software, but changing the first line of the script to #!/bin/csh -f will cause your script to not read .cshrc files at the start, protecting you from other users who made that mistake.

If your interactive shell is in the sh/ksh family you might have set LD_LIBRARY_PATH using "set" but not exported it. In that case it's new value will be set like a normal variable, but not exported into the environment. But it's more likely that your script is reinitializing the variable.
You can use the "env" command to dump out the exported environment from the interactive shell to check this.

Related

How to set environment variables in fish shell script

In my fish shell script 'hoge.fish`, I have a code to set envs.
#!/usr/local/bin/fish
set -x HOGE "hello"
but after I exec this script the env is not set correctly and outputs nothing.
./hoge.fish
echo $HOGE
I've tried these code but none of these worked.
set -gx HOGE "hello"
set -gU HOGE "hello"
how can I fix this?
OS: macOS High Sierra 10.13.6
fish version: 2.7.1
iTerm2: 3.2.0
When you ran the script, it probably set the environment variable correctly, but only in the process that was created when you ran the script....not in the parent session you ran the script from! When the script exited, the process and its environment were destroyed.
If you want to change the environment variable in your current environment, depending on what interactive shell you're using, you can use a command like source hoge.fish, which will execute the commands in your current session rather than a subprocess, so the environment variable changes will persist.
While sourceing, as in the original answer is definitely the correct mechanism, a comment from the OP to that answer mentioned that they would still prefer a solution that could be executed as a script.
As long as the variables are exported (set -x) in the script, it's possible (but still not necessarily recommended) to do this by execing into another fish shell inside the script:
#!/usr/bin/env fish
set -gx HOGE hello
exec fish
Executing ./hoge.fish will then have a fish shell with HOGE set as expected.
However, be aware:
This will result in two fish shell processes running, one inside the other. The first (parent) is the original fish shell. It will spawn a second (child) process based on the shebang line, which will then be replaced by the third instance from the exec line.
You can reduce the number of shells that are running simultaneously by starting the script with exec ./hoge.fish. That results in the shebang script replacing the parent process, and then being replaced by the exec line at the end of the script. However, you will still have run fish's startup twice to achieve what a simple source would have done with zero additional startups.
It's also important to realize the environment of the new shell will not necessarily be the same as that of the original shell. In particular, local variables from the original shell will not be present in the exec'd shell.
There are use-cases where these pitfalls are worth execing a new shell, but most of the time a simple source will be preferred.
Consider that if you run that from bash shell it will not export the variables with the -U option because it indicates to export to "fish universe" not outside.
If you stay inside fish's shell you still can do it like this:
#!/usr/local/bin/fish
set -Ux HOGE "hello"
And this is the result:
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
~/trash $ ./hoge.fish
~/tr ash $ echo $HOGE
hello
Remember to keep the first line so fish will interpret it properly.

Perl backtick ignores everything past the first space

I have a command
my $output = `somecommand parm1 parm2`;
When I try to run this Perl script I get the message
Can't exec "somecommand" at .....
It seems it is not seeing anything past the first space in between the backticks. I have a friend who runs this in a different environment and it runs fine.
What could I have in my environment that would cause this? I am running Perl v5.20 but so is my friend.
Perl's not ignoring the command parameters, it's just mentioning only the part of the command that it has a problem with -- it can't find somecommand
Whatever your somecommand is, it's not a shell command and it's not in a directory listed in your PATH variable
Change PATH to add its location to the end and it will work for you. You can do that system-wide or you dan modify it temporarily in your Perl code by manipulating $ENV{PATH} before you run the command

Change shell within Perl script

I am looking for a nice way to get the following done:
So I have a script that I need to run in Python in Unix by calling from a Perl script that was, in turn, called from my Excel VBA macro in Windows using Plink. The Python script, due to dependency issues, has to run in either csh or bash, and I will need to use export/setenv to add a few libraries before running the script. However by default, perl runs in sh shell and as such, there is no way I can add in all the dependencies and have the Python script to run.
So, I am just wondering if there is EITHER: 1. a way for me to add dependencies to sh shell in the perl script, OR 2. force my perl script to run in csh (preferred, since for some reason .bashrc for the account runs into permission issues).
Thanks a lot!
How about "3. Set the appropriate environment variable in the Perl or Python scripts"?
$ENV{'PATH'} = ...
...
os.environ['PATH'] = os.pathsep.join(newpaths + os.environ['PATH'].split(os.pathsep))
(dunno how to get the path separator in Perl, sorz)
To force the shell to csh, try the following in Perl :
`/bin/csh -c "command_name"`;
Edit:
You can use ENV variable, like this. Try that :
$s = `/bin/bash -c 'VAR_FOO=753; echo \$VAR_FOO'`;
print $s;
I ended up just change the .cshrc script, apparently the addition to PATH, for some reason, did not work for me. After that, everything runs smoothly by putting all into one line
so basically it looks something like this
/path/to/.cshrc && /python/path/to/python
Hope that helps!

Running ksh script inside a perl code is not working

I have a Korn shell script at a location like /opt/apps/abc/folder/properties.env. I can execute it from Unix bash using the dot command:
. /opt/apps/abc/folder/properties.env
This works.
I have a Perl script abc.pl from which I am calling the script properties.env. I tried the following different:
system('/usr/bin/ksh','-c', '. /opt/apps/abc/folder/properties.env');
/usr/bin/ksh -c /opt/apps/abc/folder/properties.env;
system('. /opt/apps/abc/folder/properties.env');
None of the above work. I don't want to use exec because I want to return to the Perl script. What am I doing wrong?
The environment changes will only last as long as the life of the ksh session spawned by the system command. If you want the environment changes to affect the Perl script, then you have to source that file before you launch the Perl program.
If you need those environment variables in your perl code, (not in the environment where you called perl), you can also read and parse that properties.env and set the environment in the %ENV variable.
e.g
$ENV{'ENV_VAR1'}=VALUE_OF_ENV_VAR1
using system() spawn another process, as the other poster said. changing environment in the child does not affect the parent.

Why does my command-line not run from cron?

I have a perl script (part of the XMLTV family of "grabbers", specifically tv_grab_oztivo).
I can successfully run it like this:
/sw/bin/perl /path/to/tv_grab_oztivo --output /path/to/tv.xml
I use the full paths to everything to eliminate issues with the Working Directory. Permissions shouldn't be a problem.
So, if I run it from the Terminal (Mac OSX) it works just fine.
But when I set it to run via a cron job, nothing appears to happen at all. No output is created etc.
There isn't anything wrong with the crontab as far as I can see, because if I substitute a helloworld.pl for the actual script, it runs just fine at the right time.
So, what can I do to debug? I can see from looking at %ENV in the two cases that the environment is very different, but what other approaches can I take to debugging? How can I see the output of the cron job, which might be some kind of perl "die" message or "not found" message from the shell or whatever?
Or should I be trying to somehow give the cron version of the command the same environment as when it's running as me?
It's often because you don't get the full environment when running under cron. Best bet is to capture the ouput by using the command:
( /sw/bin/perl /path/to/tv_grab_oztivo ... ) >/tmp/qq 2>&1
and then have a look at /tmp/qq.
If it does turn out to be a missing environment, then you may need to put:
. ~/.profile
or something similar, into the execution chain of your cron job, such as:
( . ~/.profile ; /sw/bin/perl /path/to/tv_grab_oztivo ... ) >/tmp/qq 2>&1
If you're looking at %ENV in the two cases, I'd suggest that, as a first step in your perl script, set %ENV to what it is in a cron job, and then trying to run it from the command line. You may need to exec yourself once for this to take full control:
BEGIN {
if (exists $ENV{something_in_your_env_not_in_cron}) {
%ENV = (...);
exec $^X, $0, #ARGV;
}
}
Now try running it, and seeing if there's anything you can do to debug it (including running under perl -d if required). Most likely, you'll find that you end up adding items back into %ENV one at a time until it magically starts working (LD_LIBRARY_PATH is a good one for this, but ORACLE_HOME or DB2HOME for Oracle or DB2 apps might be good choices, too). Then you can either set the variable in your script, or in the crontab.
I'd run a simple shell script by absolute path from the cron command.
Inside that script, I'd ensure that I trapped stdout and stderr to a known (or knowable) file. I'd also ensure that enough of your environment is set. On Unix, you get almost no environment set at all when you run a command via cron - I'm not sure about MacOS X. The standard culprit for problems is PATH. I have a separate .cronfile that sets my working environment enough that I usually don't have problems - that's an analogue of .profile.
On occasion if you can't figure out what's going wrong with your command line, the simplest way to fix it is to turn the whole thing into a shell script. Ideally you shouldn't have to do this, but it can be the fastest way to solve the problem.
File: /files/cron1.sh
#!/bin/sh
/sw/bin/perl /path/to/tv_grab_oztivo --output /path/to/tv.xml
And then in cron:
/files/cron1.sh
This allows you to test the script independent of cron. Remember though that your login shell runs with different environment variables than cron does.
cron usually captures the output of stdout and stderr and e-mailes any output to the crontab owner.
Did you double check your crontab entry to make sure it's valid and will execute at the right time?
Make sure that the script does not need any environment variables set. Otherwise wrap it in another (bash) script, where you can set the environment variables that the other script expects.