J'utilise le serveur Ubuntu 16.04 et je souhaite utiliser l'utilitaire at
dans ma session actuelle pour faire quelque chose dans 1 minute (disons, an echo
), sans donner de date et d'heure spécifiques - à seulement 1 minute d'avance sur l'heure actuelle.
Cela a échoué:
echo 'hi' | at 1m
La raison pour laquelle je choisis at
plus sleep
est parce que les handicaps du sommeil session et est plus adapté à cet effet aux commandes de retard dans une autre session, plutôt que le travail d' un nous avec la plupart du temps. AFAIR, at
ne se comporte pas ainsi et ne handicapera pas ma séance.
Update_1
Par la réponse de Pied Piper, j'ai essayé:
(sleep 1m; echo 'hi') &
J'ai un problème avec cette méthode: le flux "hi" est imprimé dans mon invite principale et ajoute également une invite secondaire vide ( _
) juste sous l'invite principale qui le contient, voir:
USER@:~# (sleep 1m; echo 'hi') &
[1] 22731
USER@:~# hi
^C
[1]+ Done
Update_2
Par la réponse de Peter Corde, j'ai essayé:
(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
Cela fonctionne correctement dans Bash 4.4, mais pas dans certaines anciennes versions, apparemment (voir les commentaires dans la réponse). J'utilise personnellement Bash 4.3 dans mes propres environnements.
Réponses:
Non, ce n'est pas "imprimé dans votre
stdin
".Si vous appuyez sur retour, il n'essaiera pas de s'exécuter en
hi
tant que commande. C'est juste que l'arrière-planecho
impriméhi
tandis que le curseur était après votre invite.Vous souhaitez peut-être imprimer une nouvelle ligne de tête , comme
(sleep 1m && echo -e '\nhi' &)
. (Ajustez si nécessaire pour leecho
dans votre coque. Ou utilisezprintf
pour la portabilité.)J'ai mis l'
&
intérieur du sous-shell pour "renier" le travail en arrière-plan, donc vous évitez également le "bruit" de[1]+ Done
. Avec&&
entre les commandes,&
s'applique à l'ensemble de la chaîne de commandes composées, de sorte qu'il revient immédiatement à l'invite du shell au lieu d'attendre lasleep
sortie comme vous le feriez avec(sleep 1; echo ... &)
Voici ce qui se passe (avec 1 seconde de retard):
Bash ne sait pas que
echo
quelque chose a été imprimé, il ne sait donc pas qu'il doit réimprimer son invite ou nettoyer l'écran. Vous pouvez le faire manuellement aveccontrol-L
.Vous pouvez écrire une fonction shell qui obtient bash pour réimprimer son invite une fois
echo
terminé . Faire justeecho "$PS1"
ne reproduira aucun caractère déjà tapé.kill -WINCH $$
sur mon système obtient bash pour réimprimer sa ligne d'invite sans effacer l'écran, en laissanthi
une ligne seule avant l'invite. SIGWINCH est envoyé automatiquement lorsque la taille de WINdow CHANGE, et la réponse de bash se produit pour faire ce que nous voulons.Cela pourrait fonctionner avec d'autres shells, mais je n'essaye pas de rendre ce 100% portable / POSIX. ( Malheureusement, cela ne fonctionne que sur bash4.4, pas bash4.3, ou dépend d'un paramètre que je ne connais pas )
Vous pouvez facilement envelopper cela dans une fonction shell qui prend un argument de sommeil et un message.
bash 4.3 ne réimprime pas son invite après SIGWINCH, donc cela ne fonctionne pas là-bas. J'ai
shopt -s checkwinsize
activé sur les deux systèmes, mais cela ne fonctionne que sur le système Bash 4.4 (Arch Linux).Si cela ne fonctionne pas, vous pouvez essayer
(sleep 2 && echo -e '\nhi' && echo "$PS1" &)
, qui "fonctionne" si la ligne de commande est vide. (Il ignore également la possibilitéPROMPT_COMMAND
définie.)Il n'y a pas de moyen vraiment propre de mélanger la sortie du terminal avec tout ce que vous pourriez faire sur votre terminal plus tard, lorsque le minuteur se déclenche. Si vous êtes en train de faire défiler quelque chose
less
, vous pouvez facilement le manquer.Si vous cherchez quelque chose avec des résultats interactifs, je vous suggère de lire un fichier audio. par exemple avec un lecteur en ligne de commande comme
mpv
(nice fork de MPlayer2). Ou choisissez un fichier vidéo pour qu'une nouvelle fenêtre s'ouvre.Vous voudrez peut-être
echo
ouvrir un nouveau terminal xterm / konsole / gnome. Utilisez une option qui maintient le terminal ouvert après la fin de la commande.la source
Enter
événement de pression de touche, juste après l'apparition de l'écho, de sorte que je serais automatiquement ramené à l' invite principale de la console ?(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
.kill -WINCH $$
ne rafraîchit l'invite du shell en cours d' exécution dans le terminal. C'était tout l'intérêt de l'utiliser. Appuyer sur Entrée soumettrait une commande partiellement tapée, mais WINCH ne le fait pas, comme je l'ai montré. Si vous n'avez rien tapé, vous obtenez une invite vide.rm -rf ~/some/directory
, Entrée au mauvais moment pourrait potentiellement s'exécuterrm -rf ~/
. (Conseil de sécurité: finissez de taper les chemins, puis contrôlez-le et passezls
àrm -rf
, afin que le doigté gras entre à tout moment ne gâchera pas votre journée.)(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
et après que l'écho soit apparu, j'ai reçu une invite vide, seulement après avoir frappé,Enter
je suis revenu à l'invite principale ... Désolé si je vous comprends mal, je suis assez nouveau pour Bash.screen
session (et juste via SSH) sur un ancien système Ubuntu, et j'ai le comportement que vous décrivez.Le correct à l'utilisation est
at <timespec>
, où<timespec>
est la spécification de temps. Vous pouvez également utiliser l'-f
option pour spécifier le fichier contenant les commandes à exécuter. Si-f
et aucune redirection n'est utilisée, at va lire les commandes à exécuter depuis stdin (entrée standard).Dans votre exemple, pour exécuter "une commande" (j'ai choisi "une commande" pour être "écho salut" dans l'exemple ci-dessous) une minute juste après avoir appuyé sur Entrée (maintenant), le but
<timespec>
à utiliser estnow + 1 minute
. Donc, afin d'obtenir le résultat souhaité avec une solution à une ligne, veuillez utiliser la commande ci-dessous:echo 'echo hi' | at now + 1 minute
Ceci est supposé (et fera) pour exécuter la
echo hi
commande après une minute. Le problème ici est que laecho hi
commande sera exécutée par la commande at dans un terminal factice et la sortie sera envoyée à la boîte aux lettres de l'utilisateur (si elle est correctement configurée - ce qui nécessite une explication plus détaillée sur la façon de configurer une boîte aux lettres dans une machine Unix et ne fait pas partie de la portée de cette question). L'essentiel est que vous ne pourrez pas voir directement le résultatecho hi
dans le même terminal que vous avez émis la commande. L'alternative la plus simple est de la rediriger vers "un fichier", par exemple:echo 'echo hi > /tmp/at.out' | at now + 1 minute
Dans l'exemple ci-dessus, "certains fichiers" est
/tmp/at.out
et le résultat attendu est que le fichierat.out
sous / tmp est créé après une minute et contient le texte "hi".En plus de l'
now + 1 minute
exemple ci-dessus, de nombreuses autres spécifications de temps peuvent être utilisées, même certaines complexes. La commande at est suffisamment intelligente pour interpréter des textes assez lisibles comme les exemples ci-dessous:now + 1 day
,13:25
,mid‐night
,noon
, ...Veuillez vous référer à la page de manuel de pour plus d'informations sur les spécifications d'heure possibles car les variations possibles sont assez étendues et peuvent inclure des dates, des heures relatives ou absolues, etc.
la source
at
envoie par défaut la sortie par courrier, mais cela doit être correctement configuré pour fonctionner.at <timespec>
et le drapeau que vous avez utilisé et s'il convient à Ubuntu 16.04 xenial.Exécutez le
sleep
dans un sous-shell:Remarque: sous Linux, vous pouvez donner l'argument pour dormir en quelques secondes ou avec un suffixe s / m / h / d (pour secondes, minutes, heures, jours). Sur BSD, l'argument doit être en secondes
la source
stdin
) et non dans monstdout
(comme il le ferait avec un régulierecho
).(sleep 10s; echo 'hi') & 1>
. J'en lis maintenant plus à ce sujet.stdin
etstdout
. Ils n'ont rien à voir avec l'endroit où les choses apparaissent sur votre terminal; au lieu de cela, vous devez les interpréter par rapport à un processus particulier (essentiellement, un programme). L'entrée standard ("stdin") d'un processus est une source à partir de laquelle le processus peut lire des données et la sortie standard du processus ("stdout") est une destination vers laquelle il peut écrire des données. Ces sources et destinations peuvent être d'autres programmes ou fichiers, ou le terminal lui-même (les choses que vous tapez vont à stdin, et tout ce qui vient à stdout est affiché).Cela a échoué car vous canalisez la sortie de
echo "hi"
, ce qui est justehi
pourat
, maisat
attend que son entrée puisse être exécutée par le shell système par défaut (généralement bash, mais parfois quelque chose de différent selon le système).Cette:
réalisera ce que vous semblez essayer de faire. Il utilise une construction shell appelée `` ici document '', qui est généralement la méthode acceptée pour faire ce type de chose (car il gère plusieurs lignes mieux que l'utilisation de la
echo
commande et ne nécessite pas de créer un nouveau fichier comme vous le feriez aveccat
), et se traduit par l'équivalent un peu plus compliqué en utilisantecho
:Il est probablement intéressant de noter que la
at
commande enverra toute sortie de commande à l'utilisateur qui a invoqué laat
commande, au lieu de contourner la sortie vers le terminal comme lesleep
ferait une commande retardée dans un sous-shell. En particulier, cela signifie qu'à moins que vous n'ayez effectué une personnalisation du système ou que vous ayez l'intention de lire votre spool de messagerie local, vous ne pourrez pas obtenir la sortie des commandes exécutées viaat
.la source
syntax error. Last token seen: m Garbled time
. Je ne sais pas pourquoi. J'utilise Ubuntu 16.04, Bash 4.0. Vous l'avez peut-être fait sur un autre système. Même lorsque je tape justeat
sans autre argument --- j'obtiens toujours cette même erreur. Plus de données ici .at 1m
ne fonctionne pas pour un posix compatibleat
. La commande devrait êtreat now + 1 minute
at
, je supposais simplement que vous aviez une version qui acceptait cette syntaxe.at 1m
n'est pas POSIX, mais les implémentations compatibles POSIXat
sont libres de l'interpréter comme elles le souhaitent, cela ne rend pas uneat
implémentation moins conforme de l'interpréter comme signifiant la même chose quenow + 1 minute
de renvoyer une erreur ou signifiant il y a un mois . IOW, c'est leat 1m
code qui n'est pas POSIX.Combinez la réponse de @Peter Cordes et cette réponse /programming/23125527/how-to-return-to-bash-prompt-after-printing-output-from-backgrounded-function/23125687#23125687
Le code ci-dessous est de la dernière réponse, avec un petit changement de la mienne. Compilez-le pour déposer a.out (quel que soit le nom que vous aimez)
Exécutez ensuite la commande ci-dessous. (Je mets a.out dans dir / tmp /, vous devrez peut-être changer pour le vôtre)
ou
BTW,
kill -WINCH $$
fonctionne très bien pour moi avec Bash 4.3 sur Gentoo.la source
En s'appuyant sur les réponses ci-dessus, vous pouvez demander à la commande intégrée de diriger sa sortie vers votre terminal, comme suit:
echo "echo hi >$(tty); kill -WINCH $$" | at now + 1 minute
La
tty
commande renvoie le chemin du périphérique de votre terminal actuel, l'enfermant dans$(...)
a bash l'exécute dans un sous-shell, et la commande kill envoie un signal au processus en cours qui aura bash réimprimer son invite $ PS1.la source