şu andan itibaren bir şeyler yapın (ve belki de sonucu konsolda göster)


12

Ubuntu sunucusunu 16.04 kullanıyorum ve atşimdiki oturumumdaki yardımcı programı , echobelirli bir tarih ve saat vermeden şu andan itibaren 1 dakika (diyelim ) yapmak için kullanmak istiyorum - şimdiki zamandan sadece 1 dakika önce.

Bu başarısız oldu:

echo 'hi' | at 1m

Seçtiğim nedeni atüzerinde sleepuyku handikaplar geçerli oturumu çünkü ve oldukça çoğu zaman sadece bir biz işin daha başka bir oturumda bunun daha uygun gecikme komutları etmektir. AFAIR, atbu şekilde davranmaz ve oturumumu engellemez.

Update_1

Pied Piper'ın cevabına göre denedim:

(sleep 1m; echo 'hi')  &

Bu yöntemle ilgili bir sorun var: "hi" akışı birincil istemimin içine yazdırılır ve ayrıca _içeren birincil istemin altında boş bir ikincil istemi ( ) ekler , bkz:

USER@:~# (sleep 1m; echo 'hi')  &
[1] 22731
USER@:~# hi
^C
[1]+  Done

Update_2

Peter Corde'nin cevabına göre denedim:

(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)

Bu, Bash 4.4'te düzgün çalışıyor, ancak bazı eski sürümlerde görünmüyor (cevaptaki yorumlara bakın). Ben şahsen Bash 4.3'ü kendi ortamımda kullanıyorum.


2
Keşke öldürme bayrakları GNU tarzı ve yeniden düzenlenebilseydi, bu yüzden "hastayı öldür" gibi gelmiyor!
NH.

Yanıtlar:


6

"Merhaba" akışı istemimde (içinde stdin) yazdırılır ve benimstdout

Hayır, var olmayan "senin basılan stdin".

Return tuşuna basarsanız, hikomut olarak çalıştırmayı denemez. Sadece imleç isteminizde iken arka plan echobasılmış hi.


Belki de öncü bir yeni satır yazdırmak istersiniz (sleep 1m && echo -e '\nhi' &). ( echoKabuğunuzdaki için gerektiği gibi ayarlayın . Veya printftaşınabilirlik için kullanın .)

Ben &arka plan iş "reddetmek" için alt kabuk içine koymak , böylece de "gürültü" önlemek [1]+ Done. İle &&komutları arasında, &o beklemekten uzak yerine kabuk istemi sağa döner, böylece bütün bileşik-komuta zincirine geçerlidir sleepEğer alacağınız gibi çıkmak için(sleep 1; echo ... &)

İşte olacaklar (1 saniye gecikmeyle):

peter@volta:~$ (sleep 1 && echo -e '\nhi' &)
peter@volta:~$ 
hi
       # cursor is at the start of this empty line.

Bash bir echoşey yazdırdığını bilmiyor , bu yüzden istemini yeniden yazdırması veya ekranı temizlemesi gerektiğini bilmiyor. Bunu elle yapabilirsiniz control-L.

Bir kabuk işlevi yazabilirsiniz için bash alır sonra istemi yeniden yazdırmak echobittikten . Sadece yapmak echo "$PS1"zaten yazılan karakterleri yeniden üretmez. kill -WINCH $$sistemimde bash, ekranı temizlemeden bilgi istemi satırını yeniden yazdırır ve bilgi isteminden hiönce kendi başına bir satırda kalır . SIGWINCH, WINdow boyutu değiştiğinde otomatik olarak gönderilir ve bash'ın yanıtı istediğimizi yapar.

Diğer mermilerle çalışabilir, ancak bunu% 100 taşınabilir / POSIX yapmaya çalışmıyorum. ( Ne yazık ki, bu sadece bash4.3 üzerinde değil, bash4.4 üzerinde çalışır veya farkında olmadığım bazı ayarlara bağlıdır )

  # bash4.4
peter@volta:~$ (sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
peter@volta:~$ ljlksjksajflasdf dfas      # typed in 2 seconds
hi
peter@volta:~$ ljlksjksajflasdf dfas      # reprinted by Bash because of `kill -WINCH`

Bunu kolayca bir uyku bağımsız değişkeni ve bir mesaj alan bir kabuk işlevinde tamamlayabilirsiniz.

bash 4.3, SIGWINCH'den sonra istemini yeniden yazdırmaz, bu yüzden orada çalışmaz. Her shopt -s checkwinsizeiki sistemi de etkinleştirdim, ancak sadece Bash 4.4 sisteminde çalışıyor (Arch Linux).

Öyle değil çalışır ise, deneyebilirsin (sleep 2 && echo -e '\nhi' && echo "$PS1" &)hangi "eserler" komut satırı boş ise,. (Ayrıca PROMPT_COMMANDayarlanan olasılığı da yok sayar .)


Daha sonra, zamanlayıcı tetiklendiğinde terminalinizde ne yaparsanız yapın terminal çıkışını karıştırmak için gerçekten temiz bir yol yoktur. Bir şeyi kaydırmanın ortasındaysanız, lesskolayca özleyebilirsiniz.

Etkileşimli sonuçlara sahip bir şey arıyorsanız, bir ses dosyası oynatmanızı öneririm. örneğin mpv(MPlayer2'nin güzel çatalı) gibi bir komut satırı oynatıcısı ile . Veya yeni bir pencere açılacak şekilde bir video dosyası seçin.

(sleep 1 && mpv /f/share/music/.../foo.ogg </dev/null &>/dev/null &)

echoAçık olan yeni bir xterm / konsole / gnome-terminali açmak isteyebilirsiniz . Komut çıktıktan sonra terminali açık tutan bir seçenek kullanın.


Sevgili David'e teşekkür ediyorum ve başardım. Bu gerçekten aradığım şeyle en yakın olan şey. EnterYankı göründükten hemen sonra bir tuşa basma olayını taklit etmek için aşağıdaki komutu yükseltmenin bir yolu var mı , bu yüzden otomatik olarak konsolun birincil komut istemine geri getirilecek miyim? (sleep 2 && echo -e '\nhi' && kill -WINCH $$ &).
Arcticooling

@Arcticooling: kill -WINCH $$ etmez terminalde çalışan kabuğun istemi yenileyin. Bunu kullanmanın tüm amacı buydu. Enter tuşuna basmak kısmen yazılmış bir komut gönderir, ancak WINCH gösterdiğim gibi yapmaz. Hiçbir şey yazmadıysanız, boş bir bilgi istemi alırsınız.
Peter Cordes

1
Yazmaya başlarsanız rm -rf ~/some/directory, yanlış zamanda Enter komutu potansiyel olarak çalışır rm -rf ~/. (Emniyet ipucu: bitirmek yazarak yolları ve daha sonra -bir kontrol ve değişim lsiçin rm -rfyağ parmaklama her an girin böylece gününüzü berbat olmaz.)
Peter Cordes

Kablolu, idam ettim (sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)ve yankı ortaya çıktıktan sonra boş bir istem aldım, sadece vurduktan sonra Enterbirincil isteme geri döndüm ... Seni yanlış anlarsam özür dilerim, Bash için oldukça yeniyim.
Arcticooling

@Arcticooling: Konsol terminal emülatöründe Arch Linux üzerinde Bash 4.4 kullanıyorum. Komutumun en azından bash'ın diğer sürümlerine taşınabilir olmasını umuyordum, ama belki de değil :( Evet, sadece screeneski bir Ubuntu sisteminde bir oturumda (ve sadece SSH aracılığıyla) Bash 4.3'te test edildi ve açıkladığınız davranışı aldım.
Peter Cordes

13

Kullanımda doğru olan , zaman spesifikasyonunun at <timespec>nerede <timespec>olduğudur. -fYürütülecek komutları içeren dosyayı belirtmek için de bu seçeneği kullanabilirsiniz . Yeniden -fyönlendirme kullanılırsa ve hiç kullanılmazsa, (st) stdin'den (standart giriş) yürütülecek komutları okuyacaktır.

Örneğinizde, enter tuşuna basmanızdan hemen sonra "some command" komutunu (aşağıdaki örnekte "some command" u "echo hi" olarak seçtim) <timespec>kullanmak için kullanılması amaçlanmıştır now + 1 minute. Bu nedenle, tek katmanlı bir çözümle istediğiniz sonucu elde etmek için lütfen aşağıdaki komutu kullanın:

echo 'echo hi' | at now + 1 minute

Bu echo hikomutun bir dakika sonra çalıştırılması gerekiyor (ve yapacak) . Buradaki sorun, echo hikomutun kukla bir tty'de at komutu tarafından yürütülmesi ve çıktının kullanıcının posta kutusuna gönderilmesidir (doğru yapılandırılmışsa - bir posta kutusunun nasıl yapılandırılacağı hakkında daha kapsamlı bir açıklama gerektirir bir unix makinesidir ve bu sorunun kapsamına girmez). Alt satırda, echo hikomutu verdiğiniz terminalin sonucunu doğrudan göremeyeceksiniz . En kolay alternatif, onu "bazı dosyalara" yönlendirmenizdir, örneğin:

echo 'echo hi > /tmp/at.out' | at now + 1 minute

Yukarıdaki örnekte, "bir dosya" dır /tmp/at.outve beklenen sonuç, at.out/ tmp altındaki dosyanın bir dakika sonra oluşturulması ve 'hi' metnini içermesidir.

now + 1 minuteYukarıdaki örneğe ek olarak, bazı karmaşık olanlar da dahil olmak üzere başka birçok zaman spesifikasyonu kullanılabilir. At komutu, aşağıdaki örnekler gibi oldukça okunabilir olanları yorumlayacak kadar akıllıdır:

now + 1 day, 13:25, mid‐night, noon, ...

Olası varyasyonlar oldukça kapsamlı olduğundan ve tarihler, göreceli veya mutlak zamanlar vb. İçerebilir.


2
atvarsayılan olarak çıktıyı posta yoluyla gönderir, ancak bunun çalışması için düzgün yapılandırılması gerekir.
Simon Richter

Şimdi bir cevap için 100 rep lütuf sunuyoruz. Lütfen aşağıdaki lütuf mesajımı okuyun ve ne olduğunu at <timespec>ve kullandığınız bayrağı ve Ubuntu 16.04 xenial'a uygun olup olmadığını daha fazla açıklamak için düzenleyin .
Arcticooling

Tamam, cevaptaki ayrıntı düzeyini artırdım, böylece şimdi daha didaktik. Bazıları için biraz uzun soluk gelebilir, ancak işe yarayan örnekleri ve nasıl çalıştıklarını açıkça belirttiği için şüphelere yer bırakmayacağına inanıyorum.
Marcelo

7

Run sleepbir kabuktaki:

(sleep 60; echo -e '\nhi')  &

Not: Linux'ta argümanı saniyeler içinde veya s / m / h / d son ekiyle (saniye, dakika, saat, gün) uyku moduna geçirebilirsiniz. BSD'de argüman saniyeler içinde olmalı


Ben bu yöntem ile küçük bir sorun var --- "merhaba" akışı benim istemi (içinde stdin) ve benim değil stdout(normal ile olduğu gibi ) yazdırılır echo.
Arcticooling

1
Terminalinizdeki çıktının istemlerle ve diğer komutların çıkışıyla karıştırılmasını istemiyorsanız, bir yere yönlendirmeniz gerekir
PiedPiper

Bu yönlendirme @PiedPiper'da başarısız oldu (sleep 10s; echo 'hi') & 1>. Şimdi bunun hakkında daha fazla bilgi edindim.
Arcticooling

2
Belgeleri okumak her zaman iyi bir fikirdir :)
PiedPiper

1
@Arcticooling Görünüşe göre stdinve ve anlamları hakkında kafanız karıştı stdout. Terminalinizde bir şeylerin göründüğü yerle ilgisi yoktur; bunun yerine, bunları belirli bir sürece (temel olarak bir program) göre yorumlamalısınız . Bir işlem için standart girdi ("stdin"), işlemin verileri okuyabileceği bir kaynaktır ve işlemin standart çıktısı ("stdout"), veri yazabileceği bir hedeftir. Bu kaynaklar ve hedefler başka programlar veya dosyalar veya terminalin kendisi olabilir (yazdığınız şeyler stdin'e gider ve stdout'a gelen her şey görüntülenir).
David Z

3

Yani çıktısının çünkü başarısız echo "hi"adildir, hikarşı atama at's giriş varsayılan sistem kabuğu (genellikle Bash, ancak sisteme bağlı olarak bazen farklı bir şey) tarafından çalıştırılabilir bekliyor.

Bu:

at 1m << EOF
echo "hi"
EOF

yapmaya çalıştığınız şeyi başaracaksınız. Genellikle bu tür bir şey yapmanın kabul edilen yolu olan 'burada belge' adı verilen bir kabuk yapısı kullanır (çünkü echokomutu kullanmaktan çok satırları daha iyi işler ve sizin gibi yeni bir dosya oluşturmayı gerektirmez cat) kullanır ve aşağıdakileri kullanarak biraz daha karmaşık eşdeğere çevirir echo:

echo 'echo "hi"' | at 1m

Bir alt kabukta gecikmeli bir komut olarak çıkışı terminale kablolamak yerine at, atkomutu çağıran kullanıcıya herhangi bir komut çıkışını postalayacağını muhtemelen belirtmek gerekir sleep. Özellikle, sistemde bazı özelleştirmeler yapmadıysanız veya yerel posta biriktiricinizi okuma niyetinde değilseniz, komutların çıktısını çalıştıramayacağınız anlamına gelir at.


Herhangi bir nedenle, verdiğiniz her iki örnek de bana hata veriyor syntax error. Last token seen: m Garbled time . Neden olduğuna dair hiçbir fikrim yok. Ubuntu 16.04, Bash 4.0 kullanıyorum. Belki bunu başka bir sistemde yaptın. Sadece atbaşka bir argüman olmadan yazsam bile --- yine de aynı hatayı alıyorum. Daha fazla veri burada .
Arcticooling

1
at 1muyumlu bir posix için çalışmaz at. Komutun olması gerekirat now + 1 minute
PiedPiper

@PiedPiper doğru, 1m POSIX uyumlu sürümleriyle uyumlu değil at, sadece sözdizimini kabul eden bir sürümünüz olduğunu varsayıyordum.
Austin Hemmelgarn

@PiedPiper, at 1mPOSIX değildir, ancak POSIX uyumlu uygulamaları atistedikleri gibi yorumlamakta serbesttir, bir atuygulamayı bir ay öncenow + 1 minute bir hata veya anlam döndürmeyle aynı anlam olarak yorumlamak daha az uyumlu değildir . IOW, POSIX olmayan kod. at 1m
Stéphane Chazelas

2

@Peter Cordes'in cevabını ve bu cevabı birleştirin /programming/23125527/how-to-return-to-bash-prompt-after-printing-output-from-backgrounded-function/23125687#23125687

Aşağıdaki kod, küçük bir değişiklikle ikinci cevaptan. A.out dosyasına (istediğiniz adla) dosyalamak için derleyin

#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        char *tty = "/dev/tty";
        if (argc > 1)
                tty = argv[1];
        int fd = open(tty, O_WRONLY);

        int i;
        char buf[] = "\n";
        for (i = 0; i < sizeof buf - 1; i++)
                if (ioctl(fd, TIOCSTI, &buf[i]))
                        perror("ioctl");
        close(fd);
        return 0;
}

Ardından aşağıdaki komutu çalıştırın. (Dir / tmp / dizinine a.out koydum, sizinkini değiştirmeniz gerekebilir)

(sleep 2 && echo -e '\nhi' && /tmp/a.out &)

veya

(sleep 2 && echo -e '\nhi' && /tmp/a.out /proc/$$/fd/0 &)

BTW, kill -WINCH $$Gentoo'da Bash 4.3 ile benim için iyi çalışıyor.


1

Yukarıdaki yanıtlara dayanarak, gömülü komutun çıktısını terminalinize yönlendirmesini sağlayabilirsiniz, örneğin:

echo "echo hi >$(tty); kill -WINCH $$" | at now + 1 minute

ttyKomut içeri çevreleyen, geçerli terminalin cihaz yolunu döndüren $(...)bir alt kabuk içinde yürütmek bash vardır ve öldürme komut bash onun $ PS1 istemi yeniden yazdırmak zorunda kalacaktır sürecin bir sinyal gönderir.

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.