Eko gibi davranan ancak stdout'tan ziyade stderr'a çıktı veren standart bir Bash aracı var mı?
Yapabileceğimi biliyorum echo foo 1>&2
ama biraz çirkin ve şüpheli, hata eğilimli (örneğin işler değiştiğinde yanlış düzenleme olasılığı daha yüksek).
Eko gibi davranan ancak stdout'tan ziyade stderr'a çıktı veren standart bir Bash aracı var mı?
Yapabileceğimi biliyorum echo foo 1>&2
ama biraz çirkin ve şüpheli, hata eğilimli (örneğin işler değiştiğinde yanlış düzenleme olasılığı daha yüksek).
Yanıtlar:
Bunu, okumayı kolaylaştırarak yapabilirsiniz:
>&2 echo "error"
>&2
# 2 dosya tanımlayıcısını 1 numaralı dosya tanımlayıcısına kopyalar. Bu nedenle, bu yeniden yönlendirme gerçekleştirildikten sonra, her iki dosya tanıtıcısı da aynı dosyaya başvurur: bir dosya tanıtıcısı # 2 başlangıçta atıfta bulundu. Daha fazla bilgi için Bash Hackerları Resimli Yeniden Yönlendirme Eğiticisine bakın .
alias
Bir kabuk komut dosyasında bir kullanmak bilmiyorum . Muhtemelen kullanımı daha güvenli olurerrcho(){ >&2 echo $@; }
errcho(){ >&2 echo $@|pr -To5;}
işe yaramaz. Böyle bir şey yapmak için, yönlendirmeyi son borudan sonra bir yere koymak zorunda kalacaksınız:errcho(){ echo $@|>&2 pr -To5;}
Bir işlev tanımlayabilirsiniz:
echoerr() { echo "$@" 1>&2; }
echoerr hello world
Bu bir komut dosyasından daha hızlı olacaktır ve bağımlılıkları olmayacaktır.
Camilo Martin'in bash özel önerisi bir "burada dize" kullanır ve yankının normalde yutacağı argümanlar (-n) da dahil olmak üzere ilettiğiniz her şeyi yazdırır:
echoerr() { cat <<< "$@" 1>&2; }
Glenn Jackman'ın çözümü aynı zamanda yutma problemini de önler:
echoerr() { printf "%s\n" "$*" >&2; }
echoerr -ne xt
"-ne xt" yazdırmayacak. Bunun için daha iyi kullanın printf
.
echoerr() { cat <<< "$@" 1>&2; }
printf "%s\n" "$*" >&2
$IFS
halinde ayrı bir argüman olarak gönderilir boşluk echo
ile bitiştirmek araçlarla 0x20
s, ancak tip 2 daha az karakterden oluşan çok outweight kolaylık alıntı değil tehlikeleri) .
Yana 1
standart çıkışı, açıkça gibi bir çıkış yönlendirme önünde adlandırın gerekmez >
ancak bunun yerine basitçe yazabilirsiniz:
echo Bu mesaj stderr> & 2'ye gider
1>&2
Güvenilir bir şekilde yazmanızın zor olacağından endişe duyduğunuzdan , gereksizliğin ortadan kaldırılması sizin için 1
hafif bir teşvik olabilir!
Başka seçenek
echo foo >>/dev/stderr
foo
- örneğin - kendi Stderr yönlendirildi vardır foo >foo.log 2>&1
- o zaman echo foo >/dev/stderr
bundan önceki bütün çıktıyı pataklayacak. >>
yerine kullanılmalıdır:echo foo >>/dev/stderr
/dev/fd/2
.
/proc/self/fd/2
. Aşağıdaki cevabımı gör :)
Hayır, bunu yapmanın standart yolu bu. Hatalara neden olmamalıdır.
1>&2
. Hepimiz bunun gerçekleşmemesini dileriz, ancak eminim hepimiz olduğu yerler olmuştur.
( echo something 1>&2 ; something else ) > log
-> (echo something; cp some junk 1>&2 ; something else) > log
Hata.
İletiyi syslog dosyasına da kaydetmeyi önemsemiyorsanız, not_so_ugly yolu:
logger -s $msg
-S seçeneği şu anlama gelir: "İletiyi standart hataya ve sistem günlüğüne gönder."
Bu, boru girişini STDERR'a yönlendiren basit bir STDERR işlevidir.
#!/bin/bash
# *************************************************************
# This function redirect the pipe input to STDERR.
#
# @param stream
# @return string
#
function STDERR () {
cat - 1>&2
}
# remove the directory /bubu
if rm /bubu 2>/dev/null; then
echo "Bubu is gone."
else
echo "Has anyone seen Bubu?" | STDERR
fi
# run the bubu.sh and redirect you output
tux@earth:~$ ./bubu.sh >/tmp/bubu.log 2>/tmp/bubu.err
echo what | /dev/stderr
...
Not: Ben post-cevap stderr çıktı yanıltıcı / belirsiz "yankı" değil soru (zaten OP tarafından cevaplandı).
Niyeti göstermek ve istediğiniz uygulamayı kaynaklamak için bir işlev kullanın . Örneğin
#!/bin/bash
[ -x error_handling ] && . error_handling
filename="foobar.txt"
config_error $filename "invalid value!"
output_xml_error "No such account"
debug_output "Skipping cache"
log_error "Timeout downloading archive"
notify_admin "Out of disk space!"
fatal "failed to open logger!"
Ve error_handling
olmak:
ADMIN_EMAIL=root@localhost
config_error() { filename="$1"; shift; echo "Config error in $filename: $*" 2>&1; }
output_xml_error() { echo "<error>$*</error>" 2>&1; }
debug_output() { [ "$DEBUG"=="1" ] && echo "DEBUG: $*"; }
log_error() { logger -s "$*"; }
fatal() { which logger >/dev/null && logger -s "FATAL: $*" || echo "FATAL: $*"; exit 100; }
notify_admin() { echo "$*" | mail -s "Error from script" "$ADMIN_EMAIL"; }
OP'deki endişeleri ele alan nedenler:
Diğer sebepler:
Benim önerim:
echo "my errz" >> /proc/self/fd/2
veya
echo "my errz" >> /dev/stderr
echo "my errz" > /proc/self/fd/2
olacak etkili bir çıkış stderr
nedeniyle /proc/self
cari sürecine bir bağlantıdır ve /proc/self/fd
süreç açılan dosya tanımlayıcıları tutan ve daha sonra 0
, 1
ve 2
ayakta stdin
, stdout
ve stderr
sırasıyla.
/proc/self
Bağlantı MacOS çalışmıyor, ancak, /proc/self/fd/*
Android'de Termux geçerli değil /dev/stderr
. Bash betiğinden işletim sistemi nasıl algılanır? hangi varyantı kullanacağınızı belirleyerek komut dosyanızı daha taşınabilir hale getirmeniz gerekiyorsa yardımcı olabilir.
/proc/self
MacOS'ta çalışmıyor, bu yüzden daha basit bir /dev/stderr
yöntemle devam edeceğim . Ayrıca, diğer cevaplarda / yorumlarda belirtildiği gibi, >>
eklemek için kullanmak daha iyidir .
/proc/self/fd/*
Android'de Termux'da kullanılabilir, ancak mevcut değildir /dev/stderr
.
cat
Burada bahsedildiği gibi kullanmayın . cat
a, programı
sırasında echo
ve printf
(kabuk) yerleşiklere deneme vardır. Bir programın veya başka bir komut dosyasının (yukarıda da belirtildiği gibi) başlatılması, tüm maliyetleri ile yeni bir süreç oluşturmak anlamına gelir. Yerleşikleri kullanarak yazma işlevleri oldukça ucuzdur, çünkü bir işlem (-evre) oluşturmaya (yürütmeye) gerek yoktur.
Opner "çıkışı (herhangi standart bir araç olduğunu sorar boru stderr)", schort cevap: HAYIR ... neden? ... rediredcting boruları bu kavramlar üzerine kurulmuş olan unix (Linux ...) ve bash (sh) gibi sistemlerde temel bir kavramdır.
Bunun gibi notasyonlarla yönlendirmenin açıcıya katılıyorum: &2>1
modern programcılar için çok hoş değil, ama bu bash. Bash büyük ve sağlam programlar yazmak için tasarlanmamıştı, yöneticilerin daha az tuşa basmak için oraya ulaşmasına yardımcı olmak için tasarlandı ;-)
Ve en azından, yönlendirmeyi satırın herhangi bir yerine yerleştirebilirsiniz:
$ echo This message >&2 goes to stderr
This message goes to stderr
cat
birisini birisine bildirmek ile birine kedi kullanmamalarını bildirmek arasında bir fark var, çünkü bu yavaş. Kedinin doğru seçim olduğu sayısız kullanım durumu vardır, bu yüzden cevabınıza itiraz ediyorum.
echo
değişiklik istedi . Kullansa bile cat
, bir bash yönlendirmesi kullanması gerekir. neyse. Yani, burada kullanmak için hiçbir anlamı yoktur cat
. BTW cat
Günde 100 kez kullanıyorum , ama asla açıcı istediğinde bağlamda ... anladınız mı?
Son zamanlarda tökezlediğim başka bir seçenek şudur:
{
echo "First error line"
echo "Second error line"
echo "Third error line"
} >&2
Bu, çok satırlı hata çıkışını daha az hataya eğilimli hale getirirken yalnızca Bash yerleşiklerini kullanır (çünkü &>2
her satıra eklemeyi hatırlamanız gerekmez ).
cat
veya soru için konu dışı başka bir yardımcı programın kullanılmamasını tavsiye ediyor .
read
stderr'e yazdırılan ve yeniden yönlendirme hileleri yapmadan yankı gibi kullanılabilen bir kabuk yerleşik komutudur:
read -t 0.1 -p "This will be sent to stderr"
Bu -t 0.1
, bir stdin satırını bir değişkene depolayarak, okunan ana işlevselliğini devre dışı bırakan bir zaman aşımıdır.
Senaryo yap
#!/bin/sh
echo $* 1>&2
bu sizin aracınız olur.
Veya ayrı bir dosyada komut dosyası istemiyorsanız bir işlev yapın.
Mac OS X: Kabul edilen yanıtı ve birkaç diğer yanıtı denedim ve hepsi Mac'imde STDERR değil STDOUT yazdı.
Perl kullanarak standart hataya yazmanın taşınabilir bir yolu:
echo WARNING! | perl -ne 'print STDERR'