PS1 ve PROMPT_COMMAND arasındaki fark nedir


108

Bu harika konuya bir göz atarken , bazı örneklerin

PS1="Blah Blah Blah"

ve biraz kullanım

PROMPT_COMMAND="Blah Blah Blah"

(ve bazıları ikisini de kullanır) bir bash kabuğunda komut istemi ayarlarken. İkisi arasındaki fark nedir? Bir SO araması ve hatta biraz daha geniş bir Google araması bile bana sonuç vermiyor, bu yüzden yanıtı aramak için doğru yere bir bağlantı bile takdir edilecektir.

Yanıtlar:



67

PROMPT_COMMAND sıradan bash deyimleri içerebilirken, PS1 değişkeni değişkende ana bilgisayar adı için '\ h' gibi özel karakterler de içerebilir.

Örneğin burada hem PROMPT_COMMAND hem de PS1 kullanan bash istemim var. PROMPT_COMMAND'deki bash kodu, hangi git dalında olabileceğinizi belirler ve bunu, son çalıştırma işleminin çıkış durumu, pwd'nin ana bilgisayar adı ve temel adı ile birlikte gösterir. RET değişkeni, son yürütülen programın dönüş değerini saklar. Bu, bir hata olup olmadığını ve terminalde çalıştırdığım son programın hata kodunu görmek için kullanışlıdır. Tüm PROMPT_COMMAND ifadesini çevreleyen dış 'a dikkat edin. PROMPT_COMMAND değişkeni her değerlendirildiğinde bu değişkenin yeniden değerlendirilmesi için PS1'i içerir.

PROMPT_COMMAND='RET=$?;\
  BRANCH="";\
  ERRMSG="";\
  if [[ $RET != 0 ]]; then\
    ERRMSG=" $RET";\
  fi;\
  if git branch &>/dev/null; then\
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2);\
  fi;
PS1="$GREEN\u@\h $BLUE\W $CYAN$BRANCH$RED$ERRMSG \$ $LIGHT_GRAY";'

Örnek çıktı git olmayan bir dizinde şöyle görünür:

sashan@dhcp-au-122 Documents  $ false
sashan@dhcp-au-122 Documents  1 $ 

ve bir git dizininde şube adını görürsünüz:

sashan@dhcp-au-122 rework mybranch $ 

Güncelleme

Yorumları ve Bob'un cevabını okuduktan sonra, onu anlattığı gibi yazmanın daha iyi olacağını düşünüyorum. Yukarıda yazdığımdan daha sürdürülebilir, burada PS1 değişkeni PROMPT_COMMAND içinde ayarlanmıştır, bu da çalışma zamanında bash tarafından değerlendirilen süper karmaşık bir dizedir. İşe yarıyor, ama olması gerekenden daha karmaşık. Adil olmak gerekirse, PROMPT_COMMAND'i yaklaşık 10 yıl önce kendim için yazdım ve işe yaradı ve bunun hakkında çok fazla düşünmedi.

Eşyalarımı nasıl değiştirdiğimi merak edenler için, temel olarak PROMPT_COMMAND kodunu ayrı bir dosyaya (Bob'un tarif ettiği gibi) koydum ve ardından PS1 olmasını istediğim dizeyi tekrarladım:

GREEN="\[\033[0;32m\]"
CYAN="\[\033[0;36m\]"
RED="\[\033[0;31m\]"
PURPLE="\[\033[0;35m\]"
BROWN="\[\033[0;33m\]"
LIGHT_GRAY="\[\033[0;37m\]"
LIGHT_BLUE="\[\033[1;34m\]"
LIGHT_GREEN="\[\033[1;32m\]"
LIGHT_CYAN="\[\033[1;36m\]"
LIGHT_RED="\[\033[1;31m\]"
LIGHT_PURPLE="\[\033[1;35m\]"
YELLOW="\[\033[1;33m\]"
WHITE="\[\033[1;37m\]"
RESTORE="\[\033[0m\]" #0m restores to the terminal's default colour

if [ -z $SCHROOT_CHROOT_NAME ]; then
    SCHROOT_CHROOT_NAME=" "
fi
BRANCH=""
ERRMSG=""
RET=$1
if [[ $RET != 0 ]]; then
    ERRMSG=" $RET"
fi
if which git &>/dev/null; then
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2)
else
    BRANCH="(git not installed)"
fi
echo "${GREEN}\u@\h${SCHROOT_CHROOT_NAME}${BLUE}\w \
${CYAN}${BRANCH}${RED}${ERRMSG} \$ $RESTORE"

ve .bashrc dosyamda

function prompt_command {
    RET=$?
    export PS1=$(~/.bash_prompt_command $RET)
}
PROMPT_DIRTRIM=3
export PROMPT_COMMAND=prompt_command

1
Eğer çizgilerin birini kısaltabilir: if git branch &>/dev/null ; then\ . Hem stdout hem de stderr'i / dev / null'a yönlendirir. tldp.org/LDP/abs/html/io-redirection.html

3
İhracat yapmaya gerek yoktur PROMPT_COMMAND.
dolmen

2
Ceving'in yorumunun bu cevap için de çok doğru olduğunu düşünüyorum:Don't set PS1 in PROMPT_COMMAND! Set variables in PROMPT_COMMAND and use them in PS1
phil294

2
Bir neden göremiyorum, PS1içeride çevrimiçi değişimin PROMPT_COMMANDdezavantajlı olmasının nedeni . Mükemmel kullanışlı bir koddur. Bob'un yanıtının aksine, PS1değişken doğru bir şekilde oluşturuldu. Bu, gerçek durumunuza bağlı olarak çok daha karmaşık bir bash istemine izin verir.
Christian Wolf

2
@ChristianWolf'un PS1iç yapısı PROMPT_COMMANDhiçbir amaca hizmet etmez. nasıl yapılmayacağına bir örnek. inşa PS1kez .bash_profile, sadece yerine çift tırnak tek tırnak kullanabilirsiniz değişken ikameler her istemi sırasında değerlendirilecektir böylece.
pal

46

Aradaki fark, PS1'in kullanılan gerçek komut istemi dizesi olması ve PROMPT_COMMAND'in, komut isteminden hemen önce yürütülen bir komut olmasıdır. Bir bilgi istemi oluşturmanın en basit, en esnek yolunu istiyorsanız, şunu deneyin:

Bunu .bashrc dosyanıza ekleyin:

function prompt_command {
  export PS1=$(~/bin/bash_prompt)
}
export PROMPT_COMMAND=prompt_command

Sonra bir komut dosyası (bash, perl, ruby: seçiminiz) yazın ve ~ / bin / bash_prompt içine yerleştirin.

Komut dosyası, istemi oluşturmak için istediği herhangi bir bilgiyi kullanabilir. Bu çok daha basit bir IMO'dur çünkü sadece PS1 değişkeni için geliştirilmiş biraz barok ikame dilini öğrenmek zorunda değilsiniz.

PROMPT_COMMAND'i doğrudan ~ / bin / bash_prompt'a ayarlayarak ve PS1'i boş dizeye ayarlayarak da aynısını yapabileceğinizi düşünebilirsiniz. Bu ilk başta işe yarıyor gibi görünüyor, ancak kısa süre sonra, okuma satırı kodunun PS1'in gerçek komut istemine ayarlanmasını beklediğini ve geçmişte geriye dönük kelimeleri kaydırdığınızda, sonuç olarak işler karıştığını keşfedersiniz. Bu geçici çözüm, PS1'in her zaman en son istemi yansıtmasına neden olur (çünkü işlev, kabuğun çağrılan örneği tarafından kullanılan gerçek PS1'i ayarlar) ve bu, okuma satırı ve komut geçmişinin düzgün çalışmasını sağlar.


17
Do not set PS1içinde PROMPT_COMMAND! Değişkenleri girin PROMPT_COMMANDve kullanın PS1. Aksi takdirde veya PS1gibi kaçış dizilerini kullanma yeteneğinizi kaybedersiniz . Onları yeniden icat etmelisiniz . Bu mümkün olabilir ama kaybetmek etrafında çalışmaları mümkün değildir ve hangi olmayan yazdırılabilir karakterleri başını ve sonunu işaretleyin. Bu, terminali komutun uzunluğu konusunda karıştırmadan renkleri kullanamayacağınız anlamına gelir. Ve bu, iki satırı üreten bir komutu düzenlerken kafa karıştırır . Sonunda ekranda büyük bir karmaşa var. \u\hPROMPT_COMMAND\[\]readline
ceving

1
@ceving Doğru!
PS1'inizin

3
PROMPT_COMMANDyazdırmadan önce yürütülür PS1. PS1İçeriden ayarlama konusunda herhangi bir sorun görmüyorum PROMPT_COMMAND, çünkü bittikten sonra PROMPT_COMMANDkabuk yazdırılacak PS1, hangisi değiştirildi PROMPT_COMMAND(veya bu durumda, içeriden prompt_command)?
Felipe Alvarez

3
Uyarı: PROMPT_COMMAND genellikle karakterleri doğrudan komut istemine yazdırmak için kullanılmamalıdır. PS1 dışında yazdırılan karakterler Bash tarafından sayılmaz, bu da imleci yanlış yerleştirmesine ve karakterleri temizlemesine neden olur. PS1'i ayarlamak için PROMPT_COMMAND kullanın veya gömme komutlarına bakın. (
Baş

3
Neden herkesin sadece PS1'de komut ikamesi kullanmak yerine PROMPT_COMMAND'de bazı hileler yapmaya çalıştığını anlamıyorum export PS1='$(~/bin/bash_prompt)', hata aynı şeyi yapıyor
dostum

10

Kimden man bash:

PROMPT_COMMAND

Ayarlanırsa, değer, her birincil komut istemini vermeden önce bir komut olarak yürütülür.

PS1

Bu parametrenin değeri genişletilir (aşağıdaki PROMPTING bölümüne bakın) ve birincil bilgi istemi dizesi olarak kullanılır. Varsayılan değer "\ s- \ v \ $" dır.

Sadece komut dizesini ayarlamak istiyorsanız, PS1tek başına kullanmak yeterlidir:

PS1='user \u on host \h$ '

İstemi yazdırmadan hemen önce başka bir şey yapmak istiyorsanız, kullanın PROMPT_COMMAND. Örneğin, önbelleğe alınmış yazma işlemlerini diske senkronize etmek istiyorsanız şunları yazabilirsiniz:

PROMPT_COMMAND='sync'

1
Başlığı belirleyen sıra ve ile sarmalanmış olarak dahil edilebildiğinden , terminalin başlığını PS1ihtiyaç duymadan PROMPT_COMMANDda ayarlayabilirsiniz . PS1\[\]
dolmen

1
@dolmen Pekala. O zaman dinamik olarak bir ortam değişkeni ayarlamak gibi başka bir şey yapalım.
Cyker

@Cyker, ortam değişkenini dinamik olarak ayarlayabilirsiniz PS1, sadece alt kabukta ayarlanır, böylece değerini geri alamazsınız. ama senin örneğin önemsizPS1='$(sync)user \u on host \h$ '
dostum

1

fark şu ki

  • eksik satırdan çıktı alırsanız PROMPT_COMMAND, bash isteminizi bozar
  • PS1yedekler \Hve arkadaşlar
  • PROMPT_COMMANDiçeriğini çalıştırır, içeriğini bilgi PS1istemi olarak kullanır.

PS1her bilgi isteminde değişken genişletme ve komut ikamesi yapar, isteğe bağlı koda PROMPT_COMMANDdeğer atamak PS1veya çalıştırmak için kullanmaya gerek yoktur . kolayca bir export PS1='$(uuidgen) $RANDOM'kez yapabilirsiniz .bash_profile, sadece tek tırnak kullanın


0

Evet, bunu gerçekten anlamaya çalışmak için:

  • PROMPT_COMMANDkullanışlı bir bash uygunluk değişkeni / işlevi, ama kesinlikle PS1tek başına kullanılarak yapılamayacak hiçbir şey yok, değil mi?

Demek istediğim, eğer birisi komut isteminin dışında kapsamı olan başka bir değişken ayarlamak isterse : kabuğa bağlı olarak, bu değişkenin muhtemelen dışarıda ilk olarak bildirilmesi gerekir veya (en kötü durumda) bir FIFO'da bekleyen bir şeyle süslenmek zorunda kalabilir. arayan (ve sonunda tekrar silahlandırıldı ); Bazı fantezi regex kullanarak konum, özellikle bazı sorunlar neden olabilir; ama aksi halde: bir kişi (ve belki de köşe durumlarda, açık alt kabuklarda) komut ikamesi kullanarak her şeyi başarabilir mi?$PS1$PS1$PS1\u \hPROMPT_COMMAND$PS1

Sağ?

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.