Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running system command under interactive bash shell

Tags:

bash

perl

I am trying to run a command that has been aliased in my ~/.bashrc from Perl using the system command. It works well running the command only once, but when I run it twice the second invocation is run as a background job and then suspended (the same as pressing <CTRL-Z>) and I have to type fg to complete the command. For example

use strict;
use warnings;

system ('bash -ic "my_cmd"');
system ('bash -ic "my_cmd"');

The second call never completes. The output is [1]+ Stopped a.pl.

Note:

  • The same result is obtained when replacing my_cmd with any other command, for example ls.
  • It seems not to depend of the contents of my ~/.bashrc file. I tried to remove everything from it, and the problem still persisted.

I am using Ubuntu 14.04 and Perl version 5.18.2.

Update

For debugging I reduced my ~/.bashrc to

echo "Entering ~/.bashrc .."
alias my_cmd="ls"
alias

and my ~/.bash_profile to

if [ -f ~/.bashrc ]; then
    echo "Entering ~/.bash_profile .."
    . ~/.bashrc
fi

Now running:

system ('bash -lc "my_cmd"');
system ('bash -lc "my_cmd"');

gives

Entering ~/.bash_profile ..
Entering ~/.bashrc ..
alias my_cmd='ls'
bash: my_cmd: command not found
Entering ~/.bash_profile ..
Entering ~/.bashrc ..
alias my_cmd='ls'
bash: my_cmd: command not found

and running

system ('bash -ic "my_cmd"');
system ('bash -ic "my_cmd"');

gives

Entering ~/.bashrc ..
alias my_cmd='ls'
a.pl  p.sh

[1]+  Stopped                 a.pl
like image 245
Håkon Hægland Avatar asked Dec 20 '14 14:12

Håkon Hægland


People also ask

How do I run a bash shell command?

In order to run a Bash script on your system, you have to use the “bash” command and specify the script name that you want to execute, with optional arguments. Alternatively, you can use “sh” if your distribution has the sh utility installed. As an example, let's say that you want to run a Bash script named “script”.

What is interactive mode bash?

An interactive shell is when you type in the name of the shell after you have logged in to the system. For example. 1. bash. will start an interactive bash shell.

Is bash an interactive shell?

A bash shell is considered as an interactive shell when it reads and writes data from a user's terminal. Most startup scripts examine the shell variable called PS1. Usually, PS1 is set in interactive shells, and it is unset in non-interactive shells.


Video Answer


2 Answers

Rather than using the -i switch for an interactive shell, I think you should use the -l (or --login) switch, which causes bash to act as if it had been invoked as a login shell.

Using the -l switch doesn't load ~/.bashrc by default. According to man bash, in a login shell, /etc/profile/ is loaded, followed by the first file found from ~/.bash_profile/, ~/.bash_login or ~/.profile/. On my system, I have the following in ~/.bash_profile, so ~/.bashrc is loaded:

# Source .bashrc
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

Now that your ~/.bashrc is being loaded, you need to enable the expansion of aliases, which is off in a non-interactive shell. To do this, you can add the following line before setting your aliases:

shopt -s expand_aliases
like image 94
Tom Fenech Avatar answered Oct 19 '22 00:10

Tom Fenech


A process randomly stopping - aside from ctrl-z is usually when it needs STDIN, but doesn't have it attached.

Try it with - for example passwd &. It'll background and go straight into 'stopped' state. This may well be what's happening with your bash command. -i means interactive shell, explicitly, and you're trying to do something noninteractive with it.

That's almost certainly not the best approach, you probably want to do something different. bash --login might be closer to what you're after.

like image 39
Sobrique Avatar answered Oct 19 '22 00:10

Sobrique