Ve işareti “değişkenleştirin” (arka planı bir işlem)


9

Ve işareti değişkene koymanın bir yolu olup olmadığını bilmek ve hala arka plana bir işlem göndermek için kullanmak istiyorum.

Bu çalışıyor:

BCKGRND=yes
if [ "$BCKGRND" = "yes" ]; then
    sleep 5 &
else
    sleep 5
fi

Ama bu beş çizgiyi sadece biriyle başarmak hoş olmaz mıydı? Şöyle ki:

BCKGRND='&'
sleep 5 ${BCKGRND}

Ama bu işe yaramıyor. BCKGRND ayarlanmamışsa çalışır - ancak ayarlandığında bunu bir '&' harfi ile yorumlanır ve hatalar çıkarır.


izleme ve işareti kullandıktan sonra echo $!PID döndürür
— noobninja

Yanıtlar:


9

Çağrıyı arka plan yapmak için bir değişken kullanmak mümkün değildir, çünkü komut satırı kontrol işleçleri ( &&ve gibi &) için ayrıştırıldıktan sonra değişken genişletme gerçekleşir .

Yine başka bir seçenek de çağrıları bir fonksiyona sarmak olabilir:

mayberunbg() {
  if [ "$BCKGRND" = "yes" ]; then
    "$@" &
  else
    "$@"
  fi
}

... ve değişkeni gerektiği gibi ayarlayın:

$ BCKGRND=yes mayberunbg sleep 3
[1] 14137
$
[1]+  Done                    "$@"
# or
$ BCKGRND=yes
$ mayberunbg sleep 3
[1] 14203
$
[1]+  Done                    "$@"
$ BCKGRND=no mayberunbg sleep 3
# 3 seconds later
$

Ne, hayır ed? Yine de +1, bu en temiz çözüm.
— Stephen Kitt

LOLStephenKitt; şimdi dişliler dönüyor
— Jeff Schaller

Basitliği nedeniyle eval cevabını beğendim ama arka plan yapmak istediğim gerçek gerçek dünya komutum, eval kullanarak rahat olmak için çok fazla değişkenle çok karmaşıktı. @ jeff-schaller gittiğim yöne işaret eden cevabı verdi. Bir fonksiyon yerine, tüm komutu bir değişkene koydum ve sonra komutunu & ile veya olmadan yürütmek için if if stilini kullandım.
— BrowncoatOkie

11

Bir şeyleri çevirebilir ve "ön plana alma" özelliğini değiştirebilirsiniz:

FOREGROUND=fg
sleep 5 & ${FOREGROUND}

İşlemi arka planda çalıştırmak FOREGROUNDiçin trueveya olarak ayarlayın . (Ayar FOREGROUNDiçin truearka planda çalışmasına kuşkusuz kafa karıştırıcı! Uygun değişken isimleri okuyucuya alıştırma olarak kalır.)


4
bu güzel ama iş kontrolü olmayan bir kabukta çalışmaz ( set -mkullanılmadığı sürece herhangi bir komut dosyası ).
— mosvy

9

Muhtemelen şunları kullanmanız gerekir eval:

eval "sleep 5" "$BCKGRND"

evalkabuğun verilen argümanları yeniden değerlendirmesine neden olur. &Dolayısıyla bir değişmez değer &, komutu arka plana koyarak, komutun bir argümanı olarak değil, bir komutun sonunda olarak yorumlanır .


2
İçeren bir cevap eval, dikkatle ele alınması gerektiği konusunda bir uyarı içermelidir. Örneğin bu cevaba bakınız .
— Ralf

"$BCKGRND"Boş bir tartışmayı değerlendirirken sorunun ne olduğunu anlamıyorum .
— mosvy

2
@Ralf bu durumda kesinlikle alakasız . Eval hakkında özel bir şey yoktur - örneğin, aritmetik genişletmeler yoluyla komutları yürütebilirsiniz. Belki de bash (veya herhangi bir kabuk) kullanmaya karşı böyle bir uyarı olmalı ;-)
— mosvy

1
@Kusalananda evalasıl değerlendirmeden önce argümanlarını boşluklarla birleştirecek. Sadece deneyin: eval printf "'{%s}\n'" foo "" "" "". ne olursa olsun eval foo "" "" "" "", tamamen benzerdir . eval fooIFS
— mosvy

1
Değerlendirilen komut herhangi bir özel karakter içeriyorsa çift tırnak içinde olmalıdır, örn eval 'sleep $TIMEOUT' "$BACKGROUND". Aksi takdirde, değişken başka bir değişkene genişlerse veya özel karakterler içeriyorsa çift genişletme alabilirsiniz. Ayrıca, iç içe geçmiş alıntı yapmak zor olabilir.
— Barmar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.