206 votes

node.js exécute la commande système de manière synchrone

J'ai besoin de node.js fonction

result = execSync('node -v');

qui de manière synchrone exécute la ligne de commande donnée et renvoie toutes les données de sortie (stdout) de ce texte de commande.

ps. La synchronisation est erronée. Je sais. Juste pour un usage personnel.

MISE À JOUR

Nous avons maintenant la solution de mgutz qui nous donne le code de sortie, mais pas stdout ! J'attends toujours une réponse plus précise.

MISE À JOUR

mgutz a mis à jour sa réponse et la solution est ici :)
En outre, comme dgo.a mentionné, il existe un module autonome exec-sync

MISE À JOUR 2014-07-30

ShellJS lib est arrivé. Je considère que c'est le meilleur choix pour l'instant.


MISE À JOUR 2015-02-10

ENFIN ! NodeJS 0.12 supporte execSync nativement.
Voir l'officiel documents

31 votes

Ne vous laissez pas abuser, sync n'est pas faux... MÊME en NodeJS, tout votre code est exécuté de manière synchrone à moins que vous n'appeliez explicitement une méthode asynchrone ... si tout a été réalisée de manière asynchrone rien De plus, préférer les méthodes asynchrones ne signifie pas que vos longs calculs ne bloqueront pas votre serveur. c'est un choix. le fait que les créateurs de Node aient choisi de fournir des méthodes synchrones pour le système de fichiers en plus des méthodes asynchrones montre qu'il y a aussi une place pour ces dernières.

2 votes

Où peut-on trouver la "bibliothèque d'émulation de shell Unix" dont vous parlez ?

0 votes

@Florian il veut dire ShellJS

54voto

mgutz Points 781

Voir execSync bibliothèque.

C'est assez facile à faire avec nœud-ffi . Je ne le recommanderais pas pour les processus de serveur, mais pour les utilitaires de développement général, il permet de faire les choses. Installer la bibliothèque.

npm install node-ffi

Exemple script :

var FFI = require("node-ffi");
var libc = new FFI.Library(null, {
  "system": ["int32", ["string"]]
});

var run = libc.system;
run("echo $USER");

[EDIT Jun 2012 : Comment obtenir STDOUT]

var lib = ffi.Library(null, {
    // FILE* popen(char* cmd, char* mode);
    popen: ['pointer', ['string', 'string']],

    // void pclose(FILE* fp);
    pclose: ['void', [ 'pointer']],

    // char* fgets(char* buff, int buff, in)
    fgets: ['string', ['string', 'int','pointer']]
});

function execSync(cmd) {
  var
    buffer = new Buffer(1024),
    result = "",
    fp = lib.popen(cmd, 'r');

  if (!fp) throw new Error('execSync error: '+cmd);

  while(lib.fgets(buffer, 1024, fp)) {
    result += buffer.readCString();
  };
  lib.pclose(fp);

  return result;
}

console.log(execSync('echo $HOME'));

2 votes

Comment s'y prendre pour que quelque chose soit envoyé à stdout de cela ? Tout ce que je peux obtenir, c'est le code de sortie du processus

0 votes

@cwolves : Je pense que async serait mieux ici. ( Réponse d'Ivo )

0 votes

@pvorb -- oui, sauf quand on ne peut pas utiliser async :)

32voto

falko Points 519

Utilice ShellJS module.

exécuter sans fournir de rappel.

Exemple :

var version = exec('node -v').output;

3 votes

Notez qu'au moment de la rédaction de ce document, la documentation mentionne que la méthode synchrone exec() est très gourmand en ressources humaines pour les processus de longue durée.

2 votes

Options, {silent:true} est la clé

2 votes

Ceci fait quelque chose (autre que de fournir une syntaxe plus courte) que ceci ne fait pas ? const execSync = require('child_process').execSync; code = execSync('node -v');

24voto

nab Points 1449

Il existe un excellent module de contrôle de flux dans node.js appelé bloc asynchrone . Si l'intégration du code dans une fonction est acceptable dans votre cas, l'exemple suivant peut être envisagé :

var asyncblock = require('asyncblock');
var exec = require('child_process').exec;

asyncblock(function (flow) {
    exec('node -v', flow.add());
    result = flow.wait();
    console.log(result);    // There'll be trailing \n in the output

    // Some other jobs
    console.log('More results like if it were sync...');
});

2 votes

Il a posé une question explicite sur la version de synchronisation, et non sur les bibliothèques de flux de contrôle.

24 votes

@AlexeyPetrushin Chaque question porte sur un objectif, et non sur un moyen particulier de l'atteindre. Merci pour le downvoting cependant.

1 votes

Il s'agit également d'une réponse très utile pour les utilisateurs de Windows. exec-sync o ffi Sous Windows, les frais généraux sont considérables (VC++, SDK, Python, etc.), mais cette solution est plus légère.

9voto

Ivo Wetzel Points 27802

Ceci n'est pas possible dans Node.js, les deux child_process.spawn y child_process.exec ont été conçus dès le départ pour être asynchrones.

Pour plus de détails, voir : https://github.com/ry/node/blob/master/lib/child_process.js

Si vous voulez vraiment que cela soit bloquant, puis mettre tout ce qui doit se passer ensuite dans un callback, ou construire votre propre file d'attente pour gérer cela de manière bloquante, je suppose que vous pourriez utiliser Async.js pour cette tâche.

Ou, si vous avez beaucoup trop de temps à perdre, vous pouvez utiliser Node.js lui-même.

12 votes

Étrange parce que le module du système de fichiers a des appels synchrones. Pourquoi ne pas exécuter également ?

4 votes

@Alfred Les appels sync FS sont principalement là pour le chargement des configurations au démarrage du programme.

3 votes

@IvoWetzel - tisk tisk... n'avons-nous pas appris à ne jamais dire que quelque chose est impossible ? ;) voir ma solution ci-dessous.

9voto

dgo.a Points 498

C'est la méthode la plus simple que j'ai trouvée :

exec-Sync : https://github.com/jeremyfa/node-exec-sync
(À ne pas confondre avec execSync.
Exécute la commande shell de manière synchrone. A utiliser pour les scripts de migration, les programmes cli, mais pas pour le code serveur normal.

Exemple :

var execSync = require('exec-sync');   
var user = execSync('echo $USER');
console.log(user);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X