2014-12-20 12 views
5

Próbuję uruchomić polecenie, które zostało wygładzone w moim ~/.bashrc z Perla za pomocą komendy system. Działa dobrze, uruchamiając polecenie tylko raz, ale gdy uruchomię go dwukrotnie, drugie wywołanie zostanie uruchomione jako zadanie w tle, a następnie zawieszone (tak samo, jak naciśnięcie klawisza <CTRL-Z>) i muszę wpisać fg, aby ukończyć to polecenie. Na przykład:Uruchamianie polecenia systemowego pod interaktywną powłoką bash

use strict; 
use warnings; 

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

Drugie połączenie nigdy się nie kończy. Dane wyjściowe to [1]+ Stopped a.pl.

Uwaga:

  • Taki sam wynik uzyskuje się, gdy zastąpienie my_cmd z jakiegokolwiek innego polecenia, na przykład ls.
  • Wygląda na to, że nie zależy to od zawartości mojego pliku ~/.bashrc. Próbowałem usunąć wszystko z tego, a problem nadal występował.

Używam Ubuntu 14.04 i Perl wersja 5.18.2.

Aktualizacja

Do debugowania zmniejszona mój ~/.bashrc do

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

i mój ~/.bash_profile do

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

Teraz działa:

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

daje

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 

i działa

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

daje

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

[1]+ Stopped     a.pl 

Odpowiedz

6

Zamiast za pomocą przełącznika -i na interaktywnej powłoki, myślę, że należy użyć -l (lub --login) switch, co powoduje, że bash działa tak, jakby został wywołany jako powłoka logowania.

Używanie przełącznika -l nie jest domyślnie ładowane ~/.bashrc. Zgodnie z man bash w powłoce zgłoszeniowej jest ładowany /etc/profile/, a następnie pierwszy plik znaleziony od ~/.bash_profile/, ~/.bash_login lub ~/.profile/. W moim systemie, mam następujące w ~/.bash_profile, więc ~/.bashrc jest załadowany:

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

Teraz, gdy ~/.bashrc jest załadowany, musisz włączyć ekspansję aliasów, który jest wyłączony w nieinterakcyjnym powłoki.Aby to zrobić, można dodać następujący wiersz przed ustawieniem swoich aliasów:

shopt -s expand_aliases 
+1

Działa! Wspaniały :) –

1

Proces losowo zatrzymania - oprócz ctrl-z jest zazwyczaj, gdy jest konieczne STDIN, ale nie ma go w załączeniu.

Wypróbuj za pomocą - na przykład passwd &. Będzie to tło i przejdź prosto w stan "zatrzymany". Może tak być, co dzieje się z twoim poleceniem basha. -i oznacza jawnie powłokę interaktywną i próbujesz zrobić z nią coś nieinteraktywnego.

To prawie na pewno nie najlepsze podejście, prawdopodobnie chcesz zrobić coś innego. bash --login może być bliżej tego, do czego dążysz.

0

Odpowiedź Toma Fenecha zadziałała dla mnie w Ubuntu 16.04.1 LTS z małym dodatkiem. Na górze mojego pliku ~/.bashrc skomentowałem następującą sekcję, aby jeśli powłoka nie była interaktywna (np. Powłoka logowania), ~/.bashrc jest nadal czytane. W niektórych innych wersjach Linuksa nie widzę tej sekcji.

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