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:
my_cmd
with any other command, for example ls
.~/.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
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”.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With