[英]Running system command under interactive bash shell
I am trying to run a command that has been aliased in my ~/.bashrc
from Perl using the system
command. 我正在尝试使用
system
命令运行一个在Perl的~/.bashrc
别名的命令。 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. 它只能运行一次命令,但是当我运行它两次时,第二次调用作为后台作业运行然后暂停(与按
<CTRL-Z>
),我必须输入fg
才能完成命令。 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
. 输出为
[1]+ Stopped a.pl
Note: 注意:
my_cmd
with any other command, for example ls
. my_cmd
替换为任何其他命令(例如ls
时获得相同的结果。 ~/.bashrc
file. ~/.bashrc
文件的内容。 I tried to remove everything from it, and the problem still persisted. I am using Ubuntu 14.04 and Perl version 5.18.2. 我使用的是Ubuntu 14.04和Perl版本5.18.2。
Update 更新
For debugging I reduced my ~/.bashrc
to 为了调试我将
~/.bashrc
缩减为
echo "Entering ~/.bashrc .."
alias my_cmd="ls"
alias
and my ~/.bash_profile
to 和我的
~/.bash_profile
来
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
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. 我认为您应该使用
-l
(或--login
)开关,而不是将-i
开关用于交互式shell,这会导致bash的行为就好像它已被作为登录shell调用一样。
Using the -l
switch doesn't load ~/.bashrc
by default. 默认情况下,使用
-l
开关不会加载~/.bashrc
。 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/
. 根据
man bash
,在登录shell中,加载/etc/profile/
,然后加载从~/.bash_profile/
, ~/.bash_login
或~/.profile/
找到的第一个文件。 On my system, I have the following in ~/.bash_profile
, so ~/.bashrc
is loaded: 在我的系统上,我在
~/.bash_profile
有以下内容,所以~/.bashrc
被加载:
# 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. 现在您正在加载
~/.bashrc
,您需要启用别名的扩展,这在非交互式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. 一个随机停止的过程 - 除了
ctrl-z
通常是需要STDIN但没有附加它。
Try it with - for example passwd &
. 尝试使用 - 例如
passwd &
。 It'll background and go straight into 'stopped' state. 这将是背景并直接进入'停止'状态。 This may well be what's happening with your bash command.
这很可能是你的bash命令发生的事情。
-i
means interactive shell, explicitly, and you're trying to do something noninteractive with it. -i
意味着交互式shell,显然,你正试图用它做一些非交互式的东西。
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. bash --login
可能更接近你所追求的。
Tom Fenech's answer worked for me in Ubuntu 16.04.1 LTS with a small addition. Tom Fenech的回答在Ubuntu 16.04.1 LTS中为我提供了一些补充。 At the top of my ~/.bashrc file, I commented out the following section so that if the shell is not interactive (eg, a login shell), ~/.bashrc is still read.
在〜/ .bashrc文件的顶部,我注释掉了以下部分,这样如果shell不是交互式的(例如,登录shell),仍然会读取〜/ .bashrc。 On some other versions of Linux I don't see this section.
在其他一些版本的Linux上,我没有看到这一节。
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.