CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
exec login shell

 

First page Previous page 1 2 Next page Last page  View All


sieburgh
Novice

Apr 7, 2010, 11:32 PM

Post #1 of 28 (4503 views)
exec login shell Can't Post

Hi

I'd like to exec a login shell (so make the shell read .profile)
and: let that shell execute a certain command.
I can exec an interactive login shell with:

$shell = "bin/bash";
exec $shell '-';

But.. in some cases, I'd like the shell not to be interactive, but just read it's profile and execute a single command (and exit).
I can do this in C with:

execle(shell, "-sh", "-c", command, NULL, envp);

But how to do this trick in Perl?


rovf
Veteran

Apr 12, 2010, 6:40 AM

Post #2 of 28 (4448 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post

See

perldoc -f system


sieburgh
Novice

Apr 12, 2010, 6:53 AM

Post #3 of 28 (4446 views)
Re: [rovf] exec login shell [In reply to] Can't Post

The simple answer: "see perldoc -f system"
is NOT the solution for several reasons:

A: system will execute "/bin/sh", and not the shell of my choice.

B: system will not terminate the perl-script, like exec does.
( I could fake this with: exit system() )

C: The most important: A shell started with system, does not behave like a login shell: it does not process .profile of the current directory, before executing the command. This is what I really need the shell to do, because that .profile defines the environment for the command to be executed in.


So: Thanks for the answer, but the issue is not solved yet!


rovf
Veteran

Apr 12, 2010, 7:07 AM

Post #4 of 28 (4444 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post


Quote
system will execute "/bin/sh", and not the shell of my choice.


This depends on how you call it. For instance:

system("/bin/zsh", "zsh","-f",...)


Quote
A shell started with system, does not behave like a login shell: it does not process .profile of the current directory


This is not really a Perl question, but depends on the shell. For instance, on some shells, you need to call it with a leading dash ('-') to indicate that it is a login shell. On other shells, you pass certain command line switches. Exactly what is (or what is not) a login shell is not a "magical property" which can be set from the outside, without knowing the shell.


FishMonger
Veteran / Moderator

Apr 12, 2010, 7:28 AM

Post #5 of 28 (4441 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post

You need to set the environment in the Perl script via the %ENV hash instead of trying to source .profile, then use system, or qx, or backticks to run the external program.


sieburgh
Novice

Apr 12, 2010, 10:08 AM

Post #6 of 28 (4435 views)
Re: [rovf] exec login shell [In reply to] Can't Post

Hi

Yes, I know making a shell behave like a loging shell is not standardized. However: the next two Perl-lines do the trick for bash or ksh (the only shells in use at my company). But even so: It would be ok for me if I had to switch for specific shells in the script. I don't really care how I start the shell, just as long as it works.

$shell = "bin/bash";
exec $shell '-';

So: processing the .profile is not the issue, but: doing so AND give a command is something I can do in C, but not with Perl :-( .

BTW: If possible I'd like to use exec i.s.o. system.


sieburgh
Novice

Apr 12, 2010, 10:09 AM

Post #7 of 28 (4435 views)
Re: [FishMonger] exec login shell [In reply to] Can't Post

Hi

No, setting ENV is not the only thing, a .profile does (in general) more then just setting env. variables.


FishMonger
Veteran / Moderator

Apr 12, 2010, 11:07 AM

Post #8 of 28 (4433 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post


In Reply To
Hi

No, setting ENV is not the only thing, a .profile does (in general) more then just setting env. variables.



What items in .profile do you believe can't be done in Perl?


sieburgh
Novice

Apr 12, 2010, 12:07 PM

Post #9 of 28 (4430 views)
Re: [FishMonger] exec login shell [In reply to] Can't Post

Hi

I guess that in the end, anything in a .profile could be done in Perl, however: this tool is going to be used by people who have multiple .profile files (and so, a kind of multiple HOME directories) and we want an easy way to switch from one homedir to another. This is what we have been doing for a number of years now, but: the tool that we have now is in C. I'm looking for a way to do the same in Perl. It is not a tool to be used only once, but will be part of a set of developer-tools (for internal use only).


FishMonger
Veteran / Moderator

Apr 12, 2010, 12:43 PM

Post #10 of 28 (4426 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post

Sudo - Perl extension for running a command line sudo
http://search.cpan.org/~landman/Sudo-0.32/lib/Sudo.pm

IPC::ShellCmd::Sudo - Chain sudo-ing to a different user before running the command
http://search.cpan.org/~bobtfish/IPC-ShellCmd-0.001/lib/IPC/ShellCmd/Sudo.pm

File::chdir - a more sensible way to change directories
http://search.cpan.org/~dagolden/File-chdir-0.1002/lib/File/chdir.pod


sieburgh
Novice

Apr 12, 2010, 1:08 PM

Post #11 of 28 (4422 views)
Re: [FishMonger] exec login shell [In reply to] Can't Post

Hi

Don't know yet if the hints are usefull, but at least I've got something to read...

Tnx.


rovf
Veteran

Apr 13, 2010, 1:13 AM

Post #12 of 28 (4402 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post

First, to the best I know, Perl's exec pretty directly translates to the system function exec, which you are calling from C, so there should be no difference.

Second, you *can* have bash invoke the profile AND behave like a login shell, just call it like this:


Code
bash --login -c Your command goes here


The difference imposed by -c is NOT login vs. non-login shell, but interactive vs. non-interactive shell. The logic according to which files are sourced, is different from whether -c is used or not used, but this is a different issue from whether it is a login shell.


sieburgh
Novice

Apr 13, 2010, 3:50 AM

Post #13 of 28 (4397 views)
Re: [rovf] exec login shell [In reply to] Can't Post

Hi
The 'exec' I'm calling from C is not the plain exec, but execle.

I just tried your bash command:
Created a .profile that just echoes a line:

echo "PROFILE"

And then, in that directory:

bash --login -c ls

If you were right, I'd expect to see the echo of PROFILE on my screen, but sorry: I don't.. (but do see the result of the 'ls')

I wish it was this easy...


sieburgh
Novice

Apr 13, 2010, 4:09 AM

Post #14 of 28 (4396 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post

Hello again.

Minor correction:
"bash --login -c ls"

Does indeed not source ./.profile (as I said earlier), but it DOES source ~/.profile. Maybe I can use that knowledge in my Perl script somehow.
I'm pretty hopefull in this respect!

Anyway: My Perl-hacking will have to wait for a week or so: for some reason I have to other things they pay me for..


rovf
Veteran

Apr 13, 2010, 6:29 AM

Post #15 of 28 (4394 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post


Quote
I just tried your bash command:
Created a .profile that just echoes a line:
echo "PROFILE"


Maybe your bash is broken, or you are using a very old version? I tried it with bash 3.2, and it worked (in my case, I have it read ~/.bash_profile instead of ~/.profile, but the idea is the same). Maybe you should re-post this problem in a forum dedicated to bash?


sieburgh
Novice

Apr 13, 2010, 10:14 AM

Post #16 of 28 (4386 views)
Re: [rovf] exec login shell [In reply to] Can't Post

Hi

No, my bash is not broken (and it is a recent version).
It indeed sources ~/.profile, so:the profile in the homedir, where the homedir is the one taken from /etc/passwd.
In other words: with this method I cannot source another profile in an arbitrary directory.


rovf
Veteran

Apr 14, 2010, 12:29 AM

Post #17 of 28 (4369 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post


Quote
with this method I cannot source another profile in an arbitrary directory.


Of *course* bash sources the profile in that user's home who invoked the command! Do you think bash can do mind-reading to know which directory it is supposed to search for a profile????

If you want to run bash as another user, you would need to change the uid to this user.

If you have a certain "profile" file which you want to be sourced, AND you know the path to it, you will have to tell bash explicitly to source it.


sieburgh
Novice

Apr 14, 2010, 12:54 AM

Post #18 of 28 (4368 views)
Re: [rovf] exec login shell [In reply to] Can't Post

Hi

It is not really complex: Yes, I understand the basics about unix, since 1990 or so, besides, I'm an experienced programmer, in C though.....
So: Yes I do know that a shell would read ~/.profile, but: as I explained: Instead of ~/.profile, I want it to source another .profile, in another directory and, in addition to that execute a command. I do not want to change uid.
So I do perfectly know what I want, and know for sure that it is possible in C (I've used the trick for 15 years now). The only thing I'm looking for: How do I do this from Perl?


rovf
Veteran

Apr 14, 2010, 6:49 AM

Post #19 of 28 (4355 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post


In Reply To
Yes I do know that a shell would read ~/.profile, but: as I explained: Instead of ~/.profile, I want it to source another .profile, in another directory and, in addition to that execute a command. I do not want to change uid.


OK, this is a more precise specification of your problem now.

Since bash can't have any knowledge about ".profile"'s in foreign directories, it means that we have to tell bash explicitly where the foreign profile is located (AFIK bash has no builtin function telling us the path of some users profile file, given that we have his user id or home directory).

This raises another question: As you certainly know, even a login-bash does not necessarily source your ~/.profile. For example, if ~/.bash_profile exists, that one is sourced instead. Now, do you want to duplicate this logic too, or are you just happy to source just the file ~/.profile, if you find it there?

In any case, once you have found which file you want to source, there are several ways to do this.

Assume that the file you want to source, is ~jim/.profile. One trick to achieve this, goes like this:


Code
 bash --noprofile --rcfile ~jim/.profile --norc -i  -c   ls


Here, we specify the .profile to be sourced by --rcfile, use -i because otherwise the --rcfile would be ignored, and also --noprofile, so that your *own* profile is not sourced.

Invoke this from Perl via system("...") (so that ~jim is correctly resolved), and it should work. But this is not really a Perl question; it's a bash question, and perhaps you will find a more elegant solution in a bash forum.


FishMonger
Veteran / Moderator

Apr 14, 2010, 7:47 AM

Post #20 of 28 (4353 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post

Have you tried using the modules I suggested?

[rkb@rkb-2 ~]$ cat test.pl

Code
#!/usr/bin/perl 

use strict;
use warnings;
use IPC::ShellCmd;
use IPC::ShellCmd::Sudo;

my $isc = IPC::ShellCmd->new(["ls", "-l"])
->working_dir("/root/tests")
->stdin(-filename => "/dev/null")
->chain_prog(
IPC::ShellCmd::Sudo->new(
User => 'root',
SetHome => 1,
)
)->run();

print $isc->stdout(), "\n\n";



Quote
[rkb@rkb-2 ~]$ ./test.pl
total 24
-rw-r--r-- 1 root root 19 Mar 16 05:55 check_service.conf
-rw-r--r-- 1 root root 165 Mar 16 06:23 check_service.log
-rwxr-xr-x 1 root root 593 Mar 16 06:12 check_service.pl



sieburgh
Novice

Apr 14, 2010, 8:07 AM

Post #21 of 28 (4350 views)
Re: [FishMonger] exec login shell [In reply to] Can't Post

Hi

No, I've not tried the modules yet, I'm working on some other stuff. But I guess I will try the modules, or use the other suggestions I got.

So for now: Consider the problem solved. If (next week or so) I have some more time, I'll dig into it again.


sieburgh
Novice

Apr 16, 2010, 4:01 AM

Post #22 of 28 (4272 views)
Re: [rovf] exec login shell [In reply to] Can't Post

Hi there,

After some stracing on my program written in C, and my alternative perl-script (under construction), I managed to make perl behave just like I want it:

The heart of the script:

chdir ($targetdir);
if (defined($command)){
exec $shell "-sh", "-c", $command;
} else {
exec $shell '-';
}


Suppose I have a $targetdir, with a .profile in it.
(or in fact, any other file a login shell would process)

I can start an login, interactive $shell, that will process targetdir/.profile if $command is not set and then waits for input.

If I set $command, the $shell is started (as a login non-interactive shell), it processes the targetdir/.profile, and after that, it executes $command (so: the whole perl-script in fact returns with the return value of $command).

So: no need for extra modules, so I can run this script on any machinethat has a basic perl (which was an other requirement)

It happens to work both for ksh and bash shells (haven't tested others).

As you see, the first argument to the shell depends of wheter or not there is a command to be executed. Don't ask me why, I could not find the reasons for that in the manpages.

BTW: I do know that my style of Perl-coding is more like C, but hey: that's what I'm used to!

Thanks Fishmonger and rovk for the hints,


rovf
Veteran

Apr 16, 2010, 5:29 AM

Post #23 of 28 (4269 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post


Quote
As you see, the first argument to the shell depends of wheter or not there is a command to be executed. Don't ask me why, I could not find the reasons for that in the manpages.


Are you refering to "-sh"? In C-terms, this would be argv[0] in your main program, i.e. the name which the child process is supposed to believe it was invoked as. This is not different from the C-version of exec (as I said before, they are essentially the same). bash checks argv[0], and if it starts with a '-', it acts as a login shell.

Actually your code "happens by chance" for ksh too, because ksh seems also to only check the first character. This is risky to generalize, because other shells (zsh, pdksh, scsh, ...) might behave differently. A safe solution would be to have a different invocation for each shell, i.e. for bash:

exec("/usr/bin/bash", "bash", "--login", "-c", $command);

But more seriously, if your chdir-trick really works on your platform, it *really* would mean that your bash is broken, since this is definitely NOT the documented behaviour of bash. You seem to assume that a login bash would execute the profile which it finds in the directory it is started from. This is simply not true for any bash I have encountered so far. If you read the documentation, you will see that bash always gets the profile from the home directory, not from the working directory. In fact, a behaviour like the one you assume, would break many existing scripts.

A better solution would be to set the HOME environment variable to the target directory. At least it works with bash 3.2.49. In Perl, you would do this like this:

$ENV{HOME}=$targetdir;
exec "/usr/bin/bash","bash","-c",$command;

The problem is that this isn't documented either. A new version of bash could, without giving special notice, use the information stored in /etc/passwd to get at the home directory. I wouldn't feel comfortable to use such a feature in any productive script...

Ronald


sieburgh
Novice

Apr 16, 2010, 5:56 AM

Post #24 of 28 (4266 views)
Re: [rovf] exec login shell [In reply to] Can't Post


In Reply To

Quote
As you see, the first argument to the shell depends of wheter or not there is a command to be executed. Don't ask me why, I could not find the reasons for that in the manpages.


No, refering to the perl-version, I just experimented a bit: and found out I need to pass "-" as first agrument for interactive shells and "-sh" for non-interactive shells. Only if I do it that way, the shell processes it's profile in both cases (interactive- and non-interactive).

About the ksh stuff: I'm not really sure and guess you are right, I get a headache even if I have to start ksh... For now: I know it works, and has worked this way over the last 15 years, on various linux/solaris systems.

You remark about need to sett HOME first is absolutely right, that is what I do (but forgot to mention).
In general: I modify %ENV a lot before calling the sub-shell.

The main reason: we use such sub-shells for building software in a re-producable manner. I need to rely on the fact that the environment in the sub-shell does not depend on environment changes in the ancestor of the shell (so: I do NOT just import %ENV).
Some other reasons: I need to inherit terminal-features in my subshell and XAUTHORITHY/SSH for example.
We use a specification file, in which we specify the dependencies between the ancestor shell and the sub-shell. This goes beyond the topic of this forum though. It is more something for a SCM-forum.


rovf
Veteran

Apr 16, 2010, 6:36 AM

Post #25 of 28 (3782 views)
Re: [sieburgh] exec login shell [In reply to] Can't Post


Quote
I just experimented a bit: and found out I need to pass "-" as first agrument for interactive shells and "-sh" for non-interactive shells.


May I ask you why you need to *experiment* here, when all this is clearly documented anyway in the man-page of bash (and quite a few other shells)?


Quote
You remark about need to sett HOME first is absolutely right, that is what I do (but forgot to mention).


Actually, this is what made your trick work. The chdir was unnecessary, as you could have easily found out by yourself: Just set HOME to Jim's home, then chdir to Joe's home, execute a login bash and see who's profile gets sourced.


Quote
I need to rely on the fact that the environment in the sub-shell does not depend on environment changes in the ancestor of the shell


In this case, a login shell isn't that safe either. While you don't get the parent's environment, you get instead everything which some foreign .profile does. A maintenance nightmare! If I would do this, I wouldn't let bash source *anything*, plus call it from an environment which I control.

That is, I would prepare a clean environment, and call a subshell as bash --norc -c COMMAND.

First page Previous page 1 2 Next page Last page  View All
 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives