** "Ressemble à JavaScript, le cerveau (contenu) est Ruby, (la stabilité est AC / DC)" ** Langage de script Kinx ). La langue est la bibliothèque. Alors, comment utiliser la bibliothèque.
Cette fois, c'est Process. Je l'ai fait à la hâte car il était nécessaire de démarrer un processus enfant.
System.exec()
Une interface d'exécution de commandes préparée en standard depuis longtemps. C'est facile parce que vous appelez simplement system ()
au niveau C, mais c'est gênant car il ne revient pas tant qu'il n'est pas terminé, ou vous ne pouvez pas obtenir la sortie standard. Cependant, puisque la commande est exécutée via le shell, des redirections peuvent être utilisées.
Donc, cette fois, j'ai créé une classe Process
qui peut faire plus de choses, c'est donc le favori dans cette explication.
Process
using Process
La bibliothèque Process n'est pas intégrée, utilisez donc la directive using pour la charger explicitement.
using Process;
Exec
L'objet Process est créé avec new Process (command, opts)
. L'argument est un nom de commande et un tableau d'arguments, ou une chaîne de commande. Dans le cas d'un tableau, on a l'impression de passer les arguments séparément, et dans le cas d'une chaîne de ligne de commande, il est analysé en interne et automatiquement décomposé en un format tableau.
[" ls "," -1 "]
.L'objet de processus créé a les méthodes suivantes.
Méthode | Aperçu |
---|---|
run() |
Démarrez le processus. |
launch() |
Démarrez le processus et déconnectez-vous. |
std() |
Les options passées en arguments sont renvoyées.{ in: opts.in, out: opts.out, err: opts.err } |
Pas encore en cours d'exécution à ce stade. Il démarre lorsque run ()
ou launch ()
est exécuté. run ()
renvoie un objet de la classe ProcessController
.
Run
run ()
renvoie un objet de la classe ProcessController
.
var p = new Process(["cmd","arg1"]).run();
Launch
launch ()
ne renvoie rien (ou plutôt null). La méthode consiste à ne pas prendre soin de l'enfant après l'avoir poussé.
new Process(["cmd","arg1"]).launch();
ProcessController
La classe ProcessController
retournée par run ()
a les méthodes suivantes.
Méthode | Aperçu |
---|---|
isAlive() |
Vrai si le processus est actif, s'il est déjà terminé, oudetach Faux après avoir été fait |
wait() |
Attend la fin du processus et renvoie le code de fin du processus après la fin.detach Puis renvoie 0. |
detach() |
Détachez le processus |
detach ()
est déconnecté après le démarrage du processus. Sous Linux, le fonctionnement est légèrement différent du cas de la déconnexion avec launch ()
, mais ce que vous voulez faire est le même. Le fonctionnement interne est le même sous Windows.
Sous Linux, la méthode dite ** double-fork ** est utilisée pour se déconnecter lorsque le processus est lancé, mais elle ne peut être utilisée que lorsque le processus est lancé. Il est pratiquement impossible de se déconnecter après avoir démarré un processus, et si le processus parent n'attend pas ou n'attend pas correctement, l'enfant survivra en tant que zombie.
Donc, au moment de detach ()
, je lance un thread juste pour waitpid
et je m'en occupe jusqu'à ce que l'enfant meure.
Au fait, le double-fork est Linux,
En utilisant la fonction appelée ..., vous pouvez forker le processus qui était autrefois forké, puis terminer le premier processus forké à la hâte et laisser init gérer le processus petit-fils.
Le processus parent supérieur se souvient du waitpid
du premier enfant forké. Mon petit-fils est celui qui prend soin de moi.
Wait
Voici un exemple d'attente de la fin et d'obtention du code de fin.
var p = new Process(["cmd", "arg1"]).run();
var status = p.wait();
Bien sûr, si vous avez detach
, vous ne pouvez pas l'obtenir (0 est retourné).
Detach
Le «détachement» qui est sorti plus tôt. Le processus peut également être "détaché". Si vous le séparez, la connexion avec l'enfant sera coupée. Vous n'avez pas à attendre et vous n'avez pas à vous soucier de la fin. Ou plutôt, vous ne pouvez pas le faire même si vous voulez vous en soucier.
var p = new Process(["cmd", "arg1"]).run();
p.detach();
Pipe
J'attends la pipe. Le but principal de la création de «Process» est le pipe. La fonction la plus souhaitée est de connecter librement l'entrée / sortie standard au processus enfant à un tube pour échanger des informations.
Le tube est spécifié par ʻoptsde
new Process (cmd, opts)`. Il existe trois types de paramètres comme suit.
Paramètres | Contenu |
---|---|
in |
Spécifiez l'entrée standard. Vous pouvez spécifier un objet pipe, une chaîne, $stdin |
out |
Spécifiez la sortie standard. Vous pouvez spécifier un objet pipe, une chaîne, $stdout Ou$stderr |
err |
Spécifiez la sortie d'erreur standard. Vous pouvez spécifier un objet pipe, une chaîne, $stdout Ou$stderr |
$ stdin
, $ stdout
, $ stderr
... Liez la source d'entrée et la destination de sortie à l'entrée / sortie standard de ce processus.Les objets Pipe sont créés avec «new Pipe ()». Renvoie un tableau de deux objets, [Read, Write]
, par paires. L'objet pipe a les méthodes suivantes.
Normalement, le tube Write
est spécifié comme ʻout ou ʻerr
du processus enfant et lu depuis le tube Read
.
Read Pipe
Fermez le tube après run ()
. Parce qu'il est défini lorsque run ()
est terminé.
Méthode | |
---|---|
peek() |
Renvoie 0 s'il n'y a pas de données dans le tube, supérieur à 0 s'il y en a.-1 est une erreur. |
read() |
Obtenez toutes les données de canal sous forme de chaîne. S'il n'y a pas de données, une chaîne de caractères vide est renvoyée. |
close() |
Fermez le tuyau. |
Write Pipe
Fermez le tube après run ()
. Parce qu'il est défini lorsque run ()
est terminé.
Méthode | |
---|---|
write(data) |
Écrivez des données dans le tuyau. Tout ne peut pas être écrit et le nombre d'octets écrits est renvoyé. |
close() |
Fermez le tuyau. |
La forme générale est utilisée comme suit.
using Process;
var [r1, w1] = new Pipe();
var p1 = new Process([ "ls", "-1" ], { out: w1 }).run();
w1.close(); //Je ne l'utilise plus pour que tu puisses le fermer
while (p1.isAlive() || r1.peek() > 0) {
var buf = r1.read();
if (buf.length() < 0) {
System.println("Error...");
return -1;
} else if (buf.length() > 0) {
System.print(buf);
} else {
// System.println("no input...");
}
}
System.println("");
Lorsque vous utilisez Write Pipe du côté du processus parent, cela ressemble à ceci.
using Process;
//stdin lit le tube et les sorties vers la sortie standard
[r1, w1] = new Pipe();
var p1 = new Process("cat", { in: r1, out: $stdout }).run();
r1.close(); //Je ne l'utilise plus pour que tu puisses le fermer
//Envoyer à stdin sur p1
var nwrite = w1.write("Message\n");
w1.close(); //Fermeture de tuyau, extrémité de transmission
p1.wait();
En passant, cela vous permet de contrôler la sortie standard et la sortie d'erreur standard.
new Process("cmd", { out: $stdout, err: $stdout }); //Fusionner la sortie d'erreur standard avec la sortie standard
new Process("cmd", { out: $stderr, err: $stderr }); //Fusionner la sortie standard avec la sortie d'erreur standard
new Process("cmd", { out: $stderr, err: $stdout }); //Échanger
Pipeline
Connecter des tuyaux est une tâche assez fastidieuse (ou plutôt, laquelle est ...?), J'ai donc également défini Process.pipeline
, qui fait tout en même temps. Enfin, mettez une fonction de rappel et utilisez-la comme suit.
var r = Process.pipeline(cmd1, cmd2, cmd3, ..., &(i, o, pipeline) => {
// i ...Ecrire le tube vers stdin pour la première commande
// o ...Lire le tube depuis la sortie standard de la dernière commande
// pipeline ...Objet Pipeline
// pipeline.input .......Identique à i ci-dessus
// pipeline.output ......Identique à o ci-dessus
// pipeline.peek() ...... pipeline.output.peek()Pareil que
// pipeline.read() ...... pipeline.output.read()Pareil que
// pipeline.write() ..... pipeline.input.write()Pareil que
// pipeline.isAlive() ...Vrai si un processus du pipeline est actif
// pipeline.wait() ......Attendez que tous les processus du pipeline se terminent,
//Renvoie le code de fin sous forme de tableau
//La valeur de retour du rappel reste telle qu'elle est Process.pipeline()Il devient la valeur de retour de.
return pipeline.wait();
});
Vous pouvez l'utiliser sans rappeler.
var pipeline = Process.pipeline(cmd1, cmd2, cmd3, ...);
// pipeline ...Objet Pipeline
//Omis ci-dessous.
La relation de processus enfant est différente entre Windows et Linux, c'est donc un bon point du script pour pouvoir gérer de telles choses de manière unifiée. Cependant, les commandes elles-mêmes sont différentes, il est donc difficile de les absorber. Je suis un utilisateur Windows, mais j'utilise UnxUtils pour rendre certaines commandes Unix disponibles à l'invite de commande également. (Je n'aime pas vraiment Cygwin car cela change l'environnement ...)
Alors la prochaine fois.