Node.js'de “Hata: spawn ENOENT” hata ayıklamasını nasıl yaparım?


350

Aşağıdaki hatayı aldığımda:

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: spawn ENOENT
    at errnoException (child_process.js:1000:11)
    at Process.ChildProcess._handle.onexit (child_process.js:791:34)

Düzeltmek için hangi prosedürü takip edebilirim?

Yazar notu : Bu hatayla ilgili birçok sorun, bu soruyu ileride başvurmak üzere göndermem konusunda beni teşvik etti.

İlgili sorular:


Benim durumumda, tüm execargümanı, ilk argüman olarak komutu ve ikinci argüman için bir Array olarak seçenekleri iletmek yerine, sizin gibi bir String olarak geçiriyordum. örneğin spawn( "adb logcat -c" )yerine yapıyordum spawn( "adb", [ "logcat", "-c" ] ).
Joshua Pinter

Yanıtlar:


235

NOT: Bu hata hemen hemen her zaman komutun bulunmadığından, çalışma dizini olmadığından veya yalnızca Windows hatalarından kaynaklanır.

Temel nedeni hakkında fikir edinmek için kolay bir yol buldum:

Error: spawn ENOENT

Bu hatanın sorunu, hata mesajında, çağrı sitesinin nerede olduğunu, yani hangi yürütülebilir / komutun bulunmadığını söylemek için gerçekten çok az bilgi olması, özellikle çok fazla spawn çağrısı olan büyük bir kod tabanınız olduğunda . Öte yandan, hataya neden olan kesin komutu biliyorsanız , sorunu çözmek için @ laconbass 'cevabını takip edebiliriz .

@Laconbass 'cevabında önerildiği gibi kodunuzun her yerine olay dinleyicileri eklemek yerine, hangi komutun soruna neden olduğunu bulmanın çok kolay bir yolunu buldum. Ana fikir, orijinal spawn çağrısını spawn çağrısına gönderilen argümanları yazdıran bir sargı ile sarmaktır.

İşte sarmalayıcı işlevi, index.jssunucunuzun başlangıç ​​komut dosyasının üstüne veya her ne olursa olsun.

(function() {
    var childProcess = require("child_process");
    var oldSpawn = childProcess.spawn;
    function mySpawn() {
        console.log('spawn called');
        console.log(arguments);
        var result = oldSpawn.apply(this, arguments);
        return result;
    }
    childProcess.spawn = mySpawn;
})();

Daha sonra uygulamanızı bir sonraki çalıştırışınızda, yakalanmamış istisna mesajından önce şöyle bir şey göreceksiniz:

spawn called
{ '0': 'hg',
  '1': [],
  '2':
   { cwd: '/* omitted */',
     env: { IP: '0.0.0.0' },
     args: [] } }

Bu şekilde hangi komutun gerçekten yürütüldüğünü kolayca öğrenebilir ve daha sonra nodların sorunu çözmek için çalıştırılabilir dosyayı neden bulamadığını öğrenebilirsiniz.


3
İşte başka bir fikir: sadece değiştirmek spawn()için exec()ve yeniden deneyin. exec()hangi komutu çalıştırmayı denediğini söyleyecektir .
Adam Monsen

1
Önemli: Yukarıdaki kodu, ana JS dosyasının başlangıcına olabildiğince yakın yerleştirdiğinizden emin olun. Önce diğer modülleri yüklerseniz, 'spawn' fonksiyonunu saklayabilirler ve buradaki geçersiz kılma asla çağrılmaz.
Dan Nissenbaum

1
Senaryoyu kullanma şansım yok. Hiç işe yaramıyor.
newguy

Peki bu yöntemi bir homurdanma dosyasında nasıl kullanırsınız? Bunu nereye koyacağımdan emin değilim.
Felix Eve

2
Bu benim için mükemmel çalıştı. Bunu gulpfile.js dosyamın en üstüne koydum ve bingo bango bongo, spawn logging!
Yann Duran

122

1. Adım: spawnDoğru şekilde adlandırıldığından emin olun

İlk olarak child_process.spawn (komut, argümanlar, seçenekler) için dokümanları inceleyin :

commandKomut satırı bağımsız değişkenleri ile verilen ile yeni bir işlem başlatır args. Atlanırsa, argsvarsayılan olarak boş bir Array olur.

Üçüncü argüman varsayılan olarak ek seçenekleri belirtmek için kullanılır:

{ cwd: undefined, env: process.env }

envYeni işlem tarafından görülebilecek ortam değişkenlerini belirtmek için kullanın , varsayılan değerdir process.env.

Komut satırı bağımsız değişkenleri koymadığınızdan commandve tüm spawnçağrının geçerli olduğundan emin olun . Bir sonraki adıma geçin.

Adım 2: Hata olayını yayan Olay Yayıcısını belirleme

Yapılan her çağrı için kaynak kodunu üzerinde ara spawnveya child_process.spawn, yani

spawn('some-command', [ '--help' ]);

ve orada 'hata' olayı için bir olay dinleyicisi ekleyin, böylece tam olarak 'İşlenmemiş' olarak atanan Olay Yayıcısını fark edersiniz. Hata ayıklamadan sonra, bu işleyici kaldırılabilir.

spawn('some-command', [ '--help' ])
  .on('error', function( err ){ throw err })
;

Yürüt ve 'hata' dinleyicinizin kaydedildiği dosya yolunu ve satır numarasını almalısınız. Gibi bir şey:

/file/that/registers/the/error/listener.js:29
      throw err;
            ^
Error: spawn ENOENT
    at errnoException (child_process.js:1000:11)
    at Process.ChildProcess._handle.onexit (child_process.js:791:34)

İlk iki satır hala

events.js:72
        throw er; // Unhandled 'error' event

olmadıkça bu adımı tekrarlayın. Bir sonraki adıma geçmeden önce hata yayan dinleyiciyi tanımlamalısınız.

3. Adım: Ortam değişkeninin $PATHayarlandığından emin olun

İki olası senaryo vardır:

  1. Varsayılan spawndavranışa güvenirsiniz, bu nedenle alt işlem ortamı ile aynı olur process.env.
  2. Bağımsız değişken üzerinde bir envnesneyi spawngeçiren optionsaçıklıktasınız.

Her iki senaryoda da, PATHortaya çıkan alt işlemin kullanacağı ortam nesnesindeki anahtarı incelemelisiniz .

Senaryo 1 örneği

// inspect the PATH key on process.env
console.log( process.env.PATH );
spawn('some-command', ['--help']);

Senaryo 2 örneği

var env = getEnvKeyValuePairsSomeHow();
// inspect the PATH key on the env object
console.log( env.PATH );
spawn('some-command', ['--help'], { env: env });

PATHundefinedspawnENOENTcommandYürütülebilir dosyaya mutlak bir yol olmadığı sürece herhangi bir yeri bulmak mümkün olmayacağından , (yani, ) olmaması hatayı yaymaya neden olur .

Doğru PATHşekilde ayarlandığında, bir sonraki adıma geçin. Bir dizin veya bir dizin listesi olmalıdır. Son durum olağan.

4. Adım: commandiçinde tanımlananların bir dizininde bulunduğundan emin olunPATH

ENOENTDosya adı command(yani, 'bazı komutlar') üzerinde tanımlanan dizinlerden en az birinde yoksa, Spawn hata verebilir PATH.

Öğesinin tam yerini bulun command. Çoğu linux dağıtımında, bu whichkomutla bir terminalden yapılabilir . Çalıştırılabilir dosyanın mutlak yolunu (yukarıdaki gibi) veya bulunup bulunmadığını söyler.

Komut olan ve çıkış Örnek kullanım Bulunan

> which some-command
some-command is /usr/bin/some-command

Komut bulunmadığında hangisinin ve çıktısının örnek kullanımı

> which some-command
bash: type: some-command: not found

yanlış yüklenen programlar, bulunmayan bir komutun en yaygın nedenidir . Gerekirse her komut belgesine bakın ve yükleyin.

Komut basit bir komut dosyası olduğunda, dosyadaki bir dizinden erişilebilir olduğundan emin olun PATH. Değilse, ya birine taşıyın ya da bir bağlantı kurun.

PATHDoğru bir şekilde ayarlandığını ve commanderişilebilir olduğunu belirledikten sonra , çocuk sürecinizi spawn ENOENTatılmadan ortaya çıkarabilmelisiniz .


1
Bu benim Spawn ENOENT hata ayıklama için çok yararlı oldu. Birkaç kez referans verdim. Teşekkürler!
CodeManiak

36
Ayrıca cwdseçeneklerde belirtirseniz ENOENT atılır , ancak verilen dizin mevcut değil buldum .
Daniel Imfeld

4
@DanielImfeld TOPLAM TASARRUF. Bunu söyleyen bir cevap yazmalısınız.
GreenAsJade

4
spawn('some-command', ['--help'], { env: env });Bu yanıtta 3. Adımda örnek olarak kullanıldığı ve özel bir ortam geçtiğinizde PATH, örneğin: belirttiğinizden emin olun { env: { PATH: process.env.PATH } }. Env seçeneği, varsayılan olarak geçerli env'nizden değişkenleri devralmaz.
anty

5
shell: trueSorunumu spawn seçeneklerine geçerek çözebildim .
Nickofthyme

35

As @DanielImfeld doğrulttu , sen seçeneklerinde "cwd" belirtirseniz ENOENT atılmış, ancak verilen dizin mevcut değil.


1
belirli bir dizinde komutu yürütmek için bir yolu var mı?
Mitro

Windows'ta (7), sürücü harfini de cwdsadece '/ ...' değil, 'c: / ...' yoluna eklemeniz gerekiyor gibi görünüyor
Museful

29

Windows çözümü: Düğüm arası yumurtlamaspawn ile değiştirin . Örneğin, app.js dosyanızın başında böyle:

(function() {
    var childProcess = require("child_process");
    childProcess.spawn = require('cross-spawn');
})(); 

2
bir drop-in dışında çalıştı, child_process gerek yok. Düğümün spawnSync ile tam olarak aynı şekilde, bu yüzden yerine bir damla. var spawn = require('cross-spawn'); // Spawn NPM asynchronously var child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
Bogdan Trusca

27

@ laconbass'ın yanıtı bana yardımcı oldu ve muhtemelen en doğru olanı.

Buraya geldim çünkü spawn'ı yanlış kullanıyordum. Basit bir örnek olarak:

bu yanlış:

const s = cp.spawn('npm install -D suman', [], {
    cwd: root
});

bu yanlış:

const s = cp.spawn('npm', ['install -D suman'], {
    cwd: root
});

doğru:

const s = cp.spawn('npm', ['install','-D','suman'], {
    cwd: root
});

ancak, bu şekilde yapmanızı öneririm:

const s = cp.spawn('bash');
s.stdin.end(`cd "${root}" && npm install -D suman`);
s.once('exit', code => {
   // exit
});

Bunun nedeni cp.on('exit', fn), bash kurulu olduğu sürece olayın her zaman cp.on('error', fn)tetiklenmesidir , aksi takdirde, ilk yolu kullanırsak, doğrudan 'npm' yi başlatırsak , olay ilk önce patlayabilir.


1
Bir "genel rehber" sağlamak için cevabımı yeniden düzenlemeyi düşünmek ve sorunun her bir nedenine (eksik bağımlılıklar, yanlış aramalar, yanlış ortam, ...) ayrıntılar bırakmak.
laconbass

2
bu yanıtı beğenen herkes bu yerel alternatifle de ilgilenebilir: gist.github.com/ORESoftware/7bf225f0045b4649de6848f1ea5def4c
Alexander Mills

1
Ne almayı istediğiniz bir kabuk ise o zaman kullanmalısınız çünkü downvoted child_process.execveya geçmesi shell: trueiçin spawn.
givanse

@givanse mutlaka doğru değildir - hangi kabuğu kullanmak istediğinize bağlı olarak zsh veya bash veya fsh çalıştırmak isteyebilirsiniz ve davranış da farklıdır
Alexander Mills

22

Windows'ta ENOENT için, https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505 düzeltin.

örneğin spawn ('npm', ['-v'], {stdio: 'inherit'}) ile değiştirin:

  • tüm node.js sürümü için:

    spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'})
  • node.js 5.x ve üstü için:

    spawn('npm', ['-v'], {stdio: 'inherit', shell: true})

1
Bu değişiklikler nerede yapılır?
Deilan

8
Anahtar bölüm ekliyorshell: true
Ted Nyberg

19

Bu sorunla karşılaşanspawn herkes için, diğer tüm cevaplar yardımcı olmazsa ve Windows'taysanız, Windows'ta ve PATHEXTortam değişkeninde şu anda büyük bir sorun olduğunu ve belirli çağrıların nasıl ortaya çıkmasına bağlı olarak çalışabileceğini öğrenin target komutu yüklenir.


2
Peki çözüm nedir?
Nilzor

6
Düğüm-çapraz-spawn kullanmak benim için çalıştı. Aşağıdaki cevaba bakınız: stackoverflow.com/a/35561971/507339
Nilzor

1
Neyin yanlış olduğunu bulmaya çalışırken geçirdim ve bu sorun oldu. Vazgeçtim spawnve sadece kullandım exec.
Ağustos'ta

8

Benim durumumda, gerekli bağımlı sistem kaynaklarının yüklenmemesi nedeniyle bu hatayı alıyordum.

Daha spesifik olarak, ImageMagick kullanan bir NodeJS uygulaması var. Npm paketinin yüklü olmasına rağmen, çekirdek Linux ImageMagick kurulmadı. ImageMagick'i yüklemek için uygun bir yol aldım ve bundan sonra hepsi harika çalıştı!


Pencerelerin de ImageMagick'in kurulu olması gerekir mi? Im pencerelerde test ve hata alıyorum
Somename

6

pencerelerde, shell: true seçenek benim sorunum çözüldü:

yanlış:

const { spawn } = require('child_process');
const child = spawn('dir');

doğru:

const { spawn } = require('child_process');
const child = spawn('dir', [], {shell: true});

5

Değiştiriyor musun envSeçeneği ?

O zaman bu cevaba bak.


Bir düğüm işlemi ve TIL'i ortaya çıkarmaya çalışıyordum. PATH .

Bu benim için bir çözümdü:

const nodeProcess = spawn('node', ['--help'], {
  env: {
    // by default, spawn uses `process.env` for the value of `env`
    // you can _add_ to this behavior, by spreading `process.env`
    ...process.env,
    OTHER_ENV_VARIABLE: 'test',
  }
});

4

Herkes bu sorunu ayıklamak için çok zaman harcamadan önce, çoğu zaman silerek çözülebilir node_modules paketleri ve yeniden .

Yüklemek:

Bir kilit dosyası varsa,

yarn install --frozen-lockfile

veya

npm ci

respectivly. o zaman değilse

yarn install

veya

npm i

Vay bu kadar basit bir çözüm ve benim için çalıştı! Herkes sorunu çözüp çözmediğini görmek için önce bunu denemelidir.
Nick K

2

Aynı problemle karşılaştım, ama düzeltmek için basit bir yol buldum. Öyle görünüyorspawn()Program kullanıcı tarafından PATH'a eklenmişse hata (örn. Normal sistem komutları çalışır).

Bunu düzeltmek için hangi modülü ( npm install --save which) kullanabilirsiniz:

// Require which and child_process
const which = require('which');
const spawn = require('child_process').spawn;
// Find npm in PATH
const npm = which.sync('npm');
// Execute
const noErrorSpawn = spawn(npm, ['install']);

2

require('child_process').execDaha özel bir hata mesajı için spawn yerine kullanın !

Örneğin:

var exec = require('child_process').exec;
var commandStr = 'java -jar something.jar';

exec(commandStr, function(error, stdout, stderr) {
  if(error || stderr) console.log(error || stderr);
  else console.log(stdout);
});

1

Yürütülecek modülün kurulu olduğundan veya düğüm modülü değilse komutun tam yolundan emin olun


1

Test vakalarımı çalıştırırken de bu sinir bozucu problemi yaşıyordum, bu yüzden bunu aşmanın birçok yolunu denedim. Ama benim için yol , nodejs spawn işlevini içeren ana dosyanızı içeren dizinden test çalıştırıcınızı aşağıdaki gibi çalıştırmaktır :

nodeProcess = spawn('node',params, {cwd: '../../node/', detached: true });

Örneğin, bu dosya adı test.js'dir , bu nedenle onu içeren klasöre gidin . Benim durumumda, bu gibi test klasörü:

cd root/test/

sonra benim durumda test koşucuyu çalıştırmak mocha böylece şöyle olacak:

mocha test.js

Anlamak için bir günden fazla zamanımı boşa harcadım. Zevk almak!!


1

Arama execve spawntam olarak aynı komutla (bağımsız değişkenleri atlamak) için iyi çalıştı exec(bu yüzden komutumun açık olduğunu biliyordum $PATH), ancak spawnENOENT verecek Windows bu sorunla karşılaştım . Sadece .exekullandığım komuta eklemem gerektiği ortaya çıktı :

import { exec, spawn } from 'child_process';

// This works fine
exec('p4 changes -s submitted');

// This gives the ENOENT error
spawn('p4');

// But this resolves it
spawn('p4.exe');
// Even works with the arguments now
spawn('p4.exe', ['changes', '-s', 'submitted']);

0

Debian Linux sistemindeki VS Code editöründen bir node.js programında hata ayıklamaya çalışırken bu hatayı alıyordum. Aynı şeyin Windows'ta iyi çalıştığını fark ettim. Daha önce burada verilen çözümler pek yardımcı olmadı çünkü herhangi bir “spawn” komutu yazmamıştım. Rahatsız edici kod muhtemelen Microsoft tarafından yazılmıştır ve VS Code programının başlığı altında gizlenmiştir.

Daha sonra node.js'nin Windows'ta düğüm olarak adlandırıldığını fark ettim, ancak Debian'da (ve muhtemelen Ubuntu gibi Debian tabanlı sistemlerde) buna nodejs denir. Bu yüzden bir takma ad oluşturdum - bir kök terminalden koştum

ln -s / usr / bin / düğüm / usr / local / bin / düğüm

ve bu sorunu çözdü. Aynı veya benzer bir prosedür muhtemelen node.js'nizin nodejs olarak adlandırıldığı ancak düğüm olarak adlandırılmasını bekleyen bir program çalıştırdığınız veya tam tersi olduğu durumlarda çalışır.


0

Windows Node.js kullanıyorsanız, konsoldan çalıştığını bildiğiniz, ancak Düğüm'de çalıştırılmadığında bildiğiniz bir komut vermenize neden olabilecek tırnakları işlerken bazı komik işler yapar. Örneğin şu olmalıdır çalışır:

spawn('ping', ['"8.8.8.8"'], {});

ama başarısız olur. windowsVerbatimArgumentsHile yapıyor gibi görünen tırnak / benzerleri işlemek için fevkalade belgelenmemiş bir seçenek var , sadece opts nesnenize aşağıdakileri eklediğinizden emin olun:

const opts = {
    windowsVerbatimArguments: true
};

ve emriniz işe geri dönmelidir.

 spawn('ping', ['"8.8.8.8"'], { windowsVerbatimArguments: true });

Dizinin içindeki bağımsız değişkenleri alıntılamayın
laconbass

@ laconbass Bu, konsepti iletmek için açık bir şekilde önemsiz bir örnektir ve böylece tırnak işaretleri kaldırılabilir. Ancak, argümanları kesinlikle belirtmeniz gereken durumlar vardır (örneğin içinde boşluk olan bir yola sahip bir argümanı iletmeniz gerekiyorsa: "C: \ Program Files \ ..." ). Buraya gönderdim, çünkü özel hata durumunuzun nedeni olmasa da, umarım karşılaştığım gibi Düğümün Windows'ta tırnak işlemesi nedeniyle bu şifreli hatayı yaşayan başka birine yardımcı olacaktır.
Joel B

node.js zaten bazı Kara Büyü yapar ve argümanları sessizce "düzgün" olarak aktarır. Örneğiniz, dizinin içindeki bağımsız değişkeni tırnak içine alarak belirttiğiniz belgesiz seçenek olmadan çalışmalıdır.
laconbass

Sadece kendi deneyimimi eklemek için, düğümden bir java işlemi yürütüyordum. Bu hata, argüman yerine komutun etrafındaki alıntılardan dolayı başıma geldi. Komut yolundaki boşluklarla test edin ve hala tırnak işaretleri olmadan çalışır
Troncoso

0

benim durumumda çözüm

var spawn = require('child_process').spawn;

const isWindows = /^win/.test(process.platform); 

spawn(isWindows ? 'twitter-proxy.cmd' : 'twitter-proxy');
spawn(isWindows ? 'http-server.cmd' : 'http-server');

1
Bu, belirli düzeltmeleri kazanmak için bir çözüm olsa da,
ENOENT'in

Neden olduğu hakkında hiçbir fikrim yok, ancak spawn çağrı düğüm repl olmadan çalışacaktı .cmd, ama bir daktilo jest testi başarısız. - Bu hatanın anlaşılması oldukça zor olabilir, bu cevaplar daha fazla oyu hak ediyor.
Mathieu CAROFF

0

Bu sorunu, kaynağını değiştiremediğiniz bir uygulamada yaşıyorsanız, bunu ortam değişkeni olarak NODE_DEBUGayarlanmış olarak çağırmayı düşünün child_process, ör NODE_DEBUG=child_process yarn test. Bu, hangi komut satırlarının hangi dizinde çağrıldığını ve başarısızlığın nedeni genellikle son ayrıntıyı size bildirir.


0

Bazı insanlar için bir ortam yolu veya başka bir sorun olsa da, Windows 10'da Visual Studio Code için Latex Workshop uzantısını yeni yükledim ve PDF'yi oluşturmaya / önizlemeye çalışırken bu hatayı gördüm. VS Code'u Yönetici olarak çalıştırmak sorunu benim için çözdü.


1
Yine, ilgili dosya sistemi yolu bir şekilde yapmak. Uzantı muhtemelen yönetici izinleri olmadan bir yola ulaşamıyor
laconbass

-1

Windows 8 için aynı hatayı aldım. Sorun, sistem yolunuzun ortam değişkeni eksik olmasıdır. Sistem PATH değişkeninize "C: \ Windows \ System32 \" değerini ekleyin.


-2

Ekle C:\Windows\System32\için pathortam değişkeni.

adımlar

  1. Bilgisayarıma ve özelliklere git

  2. Gelişmiş ayarlar'ı tıklayın

  3. Sonra Ortam değişkenleri hakkında

  4. Seçin Pathve ardından düzenle'yi tıklayın

  5. Henüz yoksa aşağıdakileri yapıştırın: C:\Windows\System32\

  6. Komut istemini kapatma

  7. Çalıştırmak istediğiniz komutu çalıştırın

Windows 8 Ortam değişkenleri ekran görüntüsü


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.