在交互式bash shell下运行系统命令

5
我想通过使用system命令,从Perl中运行已在我的~/.bashrc中别名化的命令。它可以成功地运行一次,但当我运行两次时,第二个调用将作为后台作业运行,然后被暂停(与按<CTRL-Z>相同),我必须键入fg来完成命令。例如:
use strict;
use warnings;

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

第二个调用从未完成,输出结果为[1]+ Stopped a.pl
注意:
  • 替换my_cmd为其他命令(例如ls),将得到相同的结果。
  • 似乎与我的~/.bashrc文件的内容无关。我尝试将其全部删除,问题仍然存在。
我使用的是Ubuntu 14.04和Perl版本5.18.2。
更新
为了调试,我将~/.bashrc文件简化为:
echo "Entering ~/.bashrc .."
alias my_cmd="ls"
alias

将我的~/.bash_profile文件更改为

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

当前正在运行:

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

提供

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

并且运行

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

提供

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

[1]+  Stopped                 a.pl
3个回答

6
与其在交互式shell中使用-i开关,我认为您应该使用-l(或--login)开关,这会导致bash表现得好像已被调用为登录shell。
使用-l开关不会默认加载~/.bashrc。根据man bash的说法,在登录shell中,将加载/etc/profile/,然后加载以下第一个找到的文件:~/.bash_profile/~/.bash_login~/.profile/。在我的系统上,我在~/.bash_profile中有以下内容,因此加载了~/.bashrc
# Source .bashrc
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

现在您的~/.bashrc已经被加载,您需要启用别名扩展功能,因为在非交互式Shell中,该功能是关闭的。为了做到这一点,在设置别名之前,您可以添加以下行:

shopt -s expand_aliases

1
除了ctrl-z之外,进程随机停止通常是因为它需要STDIN,但没有连接。例如,尝试使用passwd &。它会进入后台并直接进入“已停止”状态。这很可能是您的bash命令正在发生的事情。-i表示交互式shell,明确地,而您正在尝试执行非交互式操作。那几乎肯定不是最好的方法,您可能想要尝试其他方法。bash --login可能更接近您想要的内容。

0

Tom Fenech的答案在Ubuntu 16.04.1 LTS上对我有效,但还需做一个小修改。 在我的~/.bashrc文件顶部,我注释掉了以下部分,以便如果shell不是交互式的(例如登录shell),也会读取~/.bashrc。 在其他一些Linux版本中,我没有看到这个部分。

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接