Node.js'te komut satırı argümanları process.argv dizisinde durur: ilk eleman node ikilisinin yolu, ikincisi çalıştırılan dosyanın mutlak yolu, geri kalanı sizin verdiğiniz argümanlardır. Seçenekleri elle ayrıştırmak yerine yerleşik util.parseArgs() fonksiyonunu kullanabilirsiniz. Programın sonunda kabuğa döndüreceğiniz çıkış kodunu ise process.exitCode ile ayarlamak, process.exit() çağırmaktan genellikle daha güvenlidir.
Bu yazı, bir komut satırı aracı yazarken ihtiyaç duyacağınız process parçalarını bir araya getiriyor: argv, argv0, execArgv ve execPath farkı, parseArgs seçenekleri ve hataları, exit ile exitCode arasındaki önemli ayrım, 'beforeExit' ve 'exit' olayları, Node.js'in kullandığı çıkış kodları ve process.cwd() ile process.chdir(). process global bir nesnedir ama örneklerde belgedeki gibi node:process'ten içe aktarıyoruz.
process.argv, argv0, execArgv ve execPath

process.argv, süreç başlatılırken verilen komut satırı argümanlarını içeren bir dizidir. Belgeye göre ilk eleman process.execPath, yani süreci başlatan çalıştırılabilir dosyanın mutlak yoludur. Bir giriş dosyası verilmişse ikinci eleman o dosyanın mutlak yoludur. Sonraki elemanlar ek argümanlardır. Node.js'e özgü bayraklar (--no-warnings gibi) bu dizide görünmez; onlar process.execArgv içinde toplanır.
import { argv, execArgv } from 'node:process';
import { basename } from 'node:path';
console.log(basename(argv[0]), basename(argv[1]));
console.log(argv.slice(2));
console.log(execArgv);node --no-warnings argv.mjs rapor.csv --adet=3 -v "iki kelime"
# çıktı: node.exe argv.mjs
# çıktı: [ 'rapor.csv', '--adet=3', '-v', 'iki kelime' ]
# çıktı: [ '--no-warnings' ]Çıktıyı Windows'ta aldığımız için ikilinin adı node.exe; Linux'ta node görürsünüz. Tırnak içindeki "iki kelime" tek bir argüman olarak geldi, çünkü argümanları ayıran Node.js değil kabuktur. argv.slice(2) kalıbı bu yüzden çok yaygındır: ilk iki elemanı atıp yalnızca kullanıcı argümanlarını alır.
process.argv0, Node.js başlarken verilen orijinal argv[0] değerinin salt okunur bir kopyasıdır; süreç farklı bir adla başlatıldıysa argv[0] çözümlenmiş yolu, argv0 ise verilen adı tutar. process.execArgv ise alt süreçleri ebeveynle aynı çalışma ortamında başlatmak için kullanışlıdır; belgede bunun bu amaçla var olduğu belirtilir. Alt süreç başlatma ayrıntıları child_process yazısında.
| Özellik | İçerik | Örnek |
|---|---|---|
| process.argv | execPath, giriş dosyası ve kullanıcı argümanları | ['/usr/local/bin/node', '/home/.../app.js', 'one'] |
| process.argv0 | Orijinal argv[0] değeri | node |
| process.execArgv | Dosya adından önce verilen Node.js seçenekleri | ['--no-warnings'] |
| process.execPath | Çalışan ikilinin mutlak yolu | /usr/local/bin/node |
util.parseArgs ile seçenek ayrıştırma
util.parseArgs(), process.argv ile doğrudan uğraşmaktan daha üst düzey bir API'dir. Beklediğiniz seçenekleri bir şemayla tanımlarsınız, fonksiyon da ayrıştırılmış seçenekleri values, kalan konumsal argümanları positionals içinde döndürür. Belgeye göre bu API v20.0.0 ile deneysel olmaktan çıktı. args verilmezse varsayılan olarak execPath ve dosya adı çıkarılmış process.argv kullanılır.
import { parseArgs } from 'node:util';
const { values, positionals } = parseArgs({
options: {
adet: { type: 'string', short: 'n', default: '1' },
ayrintili: { type: 'boolean', short: 'v' },
etiket: { type: 'string', multiple: true },
},
allowPositionals: true,
});
console.log(values);
console.log(positionals);
console.log(Number(values.adet) * 2);node cli.mjs dosya.txt -n 5 -v --etiket=a --etiket b
# çıktı: [Object: null prototype] {
# çıktı: adet: '5',
# çıktı: ayrintili: true,
# çıktı: etiket: [ 'a', 'b' ]
# çıktı: }
# çıktı: [ 'dosya.txt' ]
# çıktı: 10
node cli.mjs
# çıktı: [Object: null prototype] { adet: '1' }
# çıktı: []
# çıktı: 2Birkaç noktaya dikkat edin. type yalnızca 'boolean' veya 'string' olabilir; sayı türü yoktur, bu yüzden adet değerini Number() ile çevirdik. short tek karakterlik bir takma ad tanımlar. multiple: true verilen seçenek her kullanımda diziye eklenir; verilmezse son değer geçerli olur. default, seçenek argümanlarda hiç geçmediğinde kullanılır; belge, seçenek verilmişse değeri falsy olsa bile varsayılanın uygulanmadığını belirtir. values nesnesinin prototipi null'dır; çıktıdaki [Object: null prototype] ifadesi bunu gösterir.
strict varsayılan olarak true'dur: tanımlamadığınız bir seçenek ya da yanlış türde bir değer geldiğinde hata fırlatılır. Konumsal argüman kabul etmek için allowPositionals: true vermeniz gerekir; strict modda bu varsayılan olarak kapalıdır.
node cli.mjs --bilinmeyen
# çıktı: TypeError [ERR_PARSE_ARGS_UNKNOWN_OPTION]: Unknown option '--bilinmeyen'. To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- "--bilinmeyen"
# çıktı: ... (yığın kısaltıldı)
# çıktı: code: 'ERR_PARSE_ARGS_UNKNOWN_OPTION'Kullanıcıya bu yığın izini göstermek yerine çağrıyı try/catch içine alıp err.code değerine göre kısa bir kullanım mesajı yazdırmak daha iyi bir deneyim sunar. v22.4.0 ve v20.16.0 ile gelen allowNegative seçeneği, boolean seçenekleri --no- önekiyle açıkça false yapmanıza izin verir. -- işareti ise seçeneklerin bittiğini gösterir; ondan sonraki her şey konumsal argümandır:
import { parseArgs } from 'node:util';
const args = ['--no-renk', '--', '--port'];
const { values, positionals } = parseArgs({
args,
options: { renk: { type: 'boolean', default: true } },
allowNegative: true,
allowPositionals: true,
});
console.log(values, positionals);
// çıktı: [Object: null prototype] { renk: false } [ '--port' ]Daha ayrıntılı denetim isterseniz tokens: true verebilirsiniz; dönüş değerine her argümanın türünü (option, positional, option-terminator), dizideki konumunu ve satır içi değer verilip verilmediğini anlatan bir tokens dizisi eklenir. Belgedeki örnek, bu belirteçleri yeniden işleyerek özel negatif seçenek davranışı kurmayı gösterir.
Çıkış kodları: exit mi exitCode mu?
Kabuk betikleri, CI adımları ve süreç yöneticileri bir programın başarılı olup olmadığını çıkış koduna bakarak anlar: 0 başarı, sıfırdan farklı her değer hata demektir. Node.js, olay döngüsünde bekleyen asenkron iş kalmadığında normalde 0 ile çıkar. Çıkış kodunu değiştirmenin iki yolu vardır.
process.exit([kod]) süreci senkron olarak, olabildiğince hızlı sonlandırır. Belgenin uyarısı açıktır: bu çağrı, process.stdout ve process.stderr'e yazma işlemleri dahil tamamlanmamış asenkron işler olsa bile süreci kapatır. Node.js'te stdout'a yazma bazen asenkrondur ve olay döngüsünün birkaç turuna yayılabilir; dolayısıyla process.exit() hemen öncesinde yazdığınız bir mesaj kesilip kaybolabilir. Belge bu yüzden process.exitCode değerini ayarlayıp sürecin yeni iş planlamadan doğal yolla bitmesine izin vermeyi önerir.
import process from 'node:process';
process.on('beforeExit', (code) => console.log('beforeExit, kod:', code));
process.on('exit', (code) => {
console.log('exit, kod:', code);
setTimeout(() => console.log('bu satır hiç çalışmaz'), 0);
});
const eksik = ['API_URL'].filter((ad) => !process.env[ad]);
if (eksik.length) {
console.error('Eksik değişken:', eksik.join(', '));
process.exitCode = 2;
}
console.log('betik sonu');node cikis.mjs; echo "kabuk: $?"
# çıktı: Eksik değişken: API_URL
# çıktı: betik sonu
# çıktı: beforeExit, kod: 2
# çıktı: exit, kod: 2
# çıktı: kabuk: 2Bu örnek birkaç kuralı birlikte gösteriyor. process.exitCode = 2 ataması betiği durdurmadı; "betik sonu" yine yazıldı ve süreç işi bitince 2 koduyla çıktı. 'beforeExit' olayı, olay döngüsü boşaldığında ve planlanacak iş kalmadığında tetiklenir ve dinleyiciye process.exitCode değerini verir. Belgeye göre bu olayın dinleyicisi asenkron iş başlatarak sürecin devam etmesini sağlayabilir. 'exit' olayında ise geri dönüş yoktur: dinleyiciler yalnızca senkron iş yapmalıdır, çünkü süreç dinleyiciler biter bitmez sonlanır. Bu yüzden içerideki setTimeout hiç çalışmadı.
process.on('exit', (code) => console.log('exit, kod:', code));
process.on('beforeExit', () => console.log('beforeExit çalışmaz'));
setTimeout(() => console.log('zamanlayıcı iptal'), 100);
process.exit(42);
// çıktı: exit, kod: 42
// kabukta $? değeri: 42process.exit() çağrıldığında 'beforeExit' olayı tetiklenmez; belge bunu açık sonlandırma durumları için, yakalanmamış istisnalarla birlikte, ayrıca belirtir. Bekleyen zamanlayıcı da iptal oldu. Kodun türüne de dikkat edin: v20.0.0'dan beri hem process.exit() hem process.exitCode yalnızca sayı ya da tam sayı içeren bir metin kabul eder. process.exit('bir') denediğimizde TypeError ve ERR_INVALID_ARG_TYPE kodunu aldık. Ayrıca açıkça ayarladığınız çıkış kodu, Node.js'in örtük olarak ayarladığı kodun önüne geçer; ikisi birlikte verilirse process.exit(42) argümanı exitCode değerinden önceliklidir.
Node.js'in kullandığı çıkış kodları

Kendi kodlarınızı seçerken Node.js'in özel anlam verdiği değerleri bilmek, hataları ayırt etmeyi kolaylaştırır. Belgedeki listeden en sık karşılaşacaklarınız şunlardır:
| Kod | Anlamı |
|---|---|
| 0 | Başarılı; bekleyen asenkron iş kalmadı |
| 1 | Yakalanmamış ölümcül istisna (Uncaught Fatal Exception) |
| 2 | Kullanılmıyor; Bash yerleşik komutların yanlış kullanımı için ayırır |
| 5 | V8 içinde kurtarılamaz ölümcül hata; stderr çıktısı FATAL ERROR ile başlar |
| 7 | Hata işleyicisinin kendisi hata fırlattı (örneğin uncaughtException işleyicisi) |
| 9 | Geçersiz argüman: bilinmeyen seçenek ya da değeri eksik seçenek |
| 12 | --inspect için geçersiz veya kullanılamayan port |
| 13 | Üst düzey await hiç sonuçlanmayan bir Promise bekledi |
| 124 | --process-timeout süresi doldu |
| 128 üstü | Ölümcül sinyal: 128 artı sinyal numarası (SIGABRT için 134) |
echo "throw new Error('patladı');" > hata.mjs
node hata.mjs 2>/dev/null; echo "kabuk: $?"
# çıktı: kabuk: 1
node --bilinmeyen-bayrak x.mjs; echo "kabuk: $?"
# çıktı: /usr/local/bin/node: bad option: --bilinmeyen-bayrak
# çıktı: kabuk: 9
echo "await new Promise(() => {});" > tla.mjs
node tla.mjs; echo "kabuk: $?"
# çıktı: Warning: Detected unsettled top-level await at file:///home/kullanici/proje/tla.mjs:1
# çıktı: await new Promise(() => {});
# çıktı: ^
# çıktı: kabuk: 13Çıktılardaki yerel yollar /home/kullanici/proje/ biçiminde kısaltıldı. Çıktıdaki ikili yolu da Linux biçimine çevrildi. Örneğin 2 kodu için dikkat: Node.js onu kullanmaz ama Bash bu kodu kendi yerleşik komutlarının yanlış kullanımı için ayırır. Bu yüzden kendi hata kodlarınızı seçerken Node.js'in ve kabuğun ayırdığı değerlerle çakışmamaya çalışın; yukarıdaki eksik değişken örneğinde 2 kullandık, ama gerçek bir araçta farklı bir aralık seçmek karışıklığı azaltır. Yakalanmamış hatalar ve 'uncaughtException' olayı uncaughtException ve unhandledRejection yazısında ayrıntılı anlatılıyor.
Çalışma klasörü: process.cwd ve process.chdir
process.cwd() sürecin geçerli çalışma klasörünü döndürür. Bu klasör betiğin bulunduğu klasörle aynı olmak zorunda değildir; node komutunu hangi klasörden çalıştırdıysanız odur. Göreli dosya yolları da bu klasöre göre çözülür. Betiğin kendi konumunu almak için ESM'de import.meta.dirname kullanılır; ayrıntısı __dirname ve import.meta yazısında. process.chdir() çalışma klasörünü değiştirir ve başarısız olursa istisna fırlatır:
import { chdir, cwd } from 'node:process';
import { basename } from 'node:path';
console.log(basename(cwd()));
chdir('..');
console.log(basename(cwd()));
try {
chdir('olmayan-klasor');
} catch (err) {
console.log(err.code, err.syscall);
}
// çıktı: proc
// çıktı: proje
// çıktı: ENOENT chdirÖrnekte klasör adlarını kısaltmak için basename kullandık. Belgeye göre process.chdir() Worker thread'lerde kullanılamaz. Göreli yolların nasıl birleştirildiğini path modülü yazısında, ENOENT gibi sistem hata kodlarını ENOENT ve EADDRINUSE yazısında bulabilirsiniz.
Mini örnek: küçük bir komut satırı aracı
Şimdiye kadar anlatılanları tek bir araçta birleştirelim. Aşağıdaki say.mjs, verilen kelimeleri bir ayraçla birleştirip yazar. Bilinmeyen bir seçenek ya da eksik argüman geldiğinde kullanıcıya yığın izi yerine kısa bir hata ve kullanım satırı gösterir, stderr'e yazar ve çıkış kodunu ayarlar. process.exit() hiç çağrılmıyor; süreç işi bitince kendiliğinden kapanıyor ve kabuk doğru kodu görüyor.
import { parseArgs } from 'node:util';
import process from 'node:process';
const KULLANIM = 'Kullanım: node say.mjs [--ayrac=,] [--yardim] kelime...';
let secim;
try {
secim = parseArgs({
options: {
ayrac: { type: 'string', default: ' ' },
yardim: { type: 'boolean', short: 'h' },
},
allowPositionals: true,
});
} catch (err) {
console.error(`Hata: ${err.message.split('.')[0]}`);
console.error(KULLANIM);
process.exitCode = 64;
}
if (secim) {
const { values, positionals } = secim;
if (values.yardim) {
console.log(KULLANIM);
} else if (positionals.length === 0) {
console.error('En az bir kelime verin.');
console.error(KULLANIM);
process.exitCode = 64;
} else {
console.log(positionals.join(values.ayrac));
console.log(`${positionals.length} kelime`);
}
}node say.mjs elma armut --ayrac=", "; echo "kod: $?"
# çıktı: elma, armut
# çıktı: 2 kelime
# çıktı: kod: 0
node say.mjs --renk; echo "kod: $?"
# çıktı: Hata: Unknown option '--renk'
# çıktı: Kullanım: node say.mjs [--ayrac=,] [--yardim] kelime...
# çıktı: kod: 64
node say.mjs; echo "kod: $?"
# çıktı: En az bir kelime verin.
# çıktı: Kullanım: node say.mjs [--ayrac=,] [--yardim] kelime...
# çıktı: kod: 64
node say.mjs -h; echo "kod: $?"
# çıktı: Kullanım: node say.mjs [--ayrac=,] [--yardim] kelime...
# çıktı: kod: 0Örnekte dikkat edilecek birkaç tasarım kararı var. Hata kodu olarak Node.js'in kendi listesinde anlam taşımayan bir değer (64) seçtik; böylece bu araçtan gelen 1 kodunun yakalanmamış bir istisnadan, 9 kodunun da Node.js'e verilen hatalı bir bayraktan kaynaklandığını ayırt edebilirsiniz. Seçeneklerin konumsal argümanlarla karışık sırada verilebildiğine de dikkat edin: --ayrac kelimelerden sonra gelse bile doğru ayrıştırıldı. Yardım isteği başarılı bir işlem sayıldığı için kodu 0 bıraktık. Hata mesajları stderr'e gittiği için node say.mjs elma > sonuc.txt gibi bir yönlendirmede dosyaya yalnızca asıl çıktı yazılır; stdout ve stderr ayrımının ayrıntısı console ve util.styleText yazısında.
Sık yapılan hatalar
![Sık yapılan hatalar: argv[2]'yi sabit sanmak, Hata mesajından hemen sonra process.exit() çağırmak, 'exit' dinleyicisinde asenkron iş yapmak, parseArgs değerini sayı sanmak](/assets/blog/nodejs-process-argv-exit-kodlari-b7.webp)
- argv[2]'yi sabit sanmak: Kullanıcı argümanlarının sırası değişebilir; seçenekler için
parseArgskullanın. - Hata mesajından hemen sonra process.exit() çağırmak: Çıktı borudaysa (pipe) mesaj yarıda kesilebilir.
process.exitCodeayarlayıp doğal çıkışa bırakın. - 'exit' dinleyicisinde asenkron iş yapmak: Zamanlayıcılar, dosya yazma geri çağırmaları ve ağ istekleri çalışmaz.
- parseArgs değerini sayı sanmak:
type: 'string'metin döndürür; hesaplamadan önce dönüştürün ve geçersiz girdiyi kontrol edin. - process.exit'e metin vermek: Yalnızca sayılar veya
'1'gibi tam sayı metinleri kabul edilir; aksi hâldeERR_INVALID_ARG_TYPEalırsınız. - Göreli yolları betik klasörüne göre sanmak: Göreli yollar
process.cwd()'ye göre çözülür; betiği başka klasörden çalıştırınca dosyalar bulunamaz.
Sık Sorulan Sorular
process.argv'de neden ilk iki eleman var?
İlk eleman Node.js ikilisinin yolu, ikincisi çalıştırılan dosyanın yoludur. Kullanıcı argümanları üçüncü elemandan başlar; parseArgs varsayılan olarak bu iki elemanı kendisi çıkarır.
Çıkış kodunu bir işlemden sonra nasıl kontrol ederim?
Bash ve benzeri kabuklarda komuttan hemen sonra echo $? yazın. PowerShell'de $LASTEXITCODE değişkenine bakın.
Node.js bayraklarını process.argv içinde neden göremiyorum?
Dosya adından önce yazılan Node.js seçenekleri process.argv'ye girmez; onları process.execArgv içinde bulursunuz. Dosya adından sonra yazılan her şey ise, Node.js bayrağına benzese bile programın argümanıdır. CLI belgesindeki -- işareti de Node.js seçeneklerinin bittiğini gösterir; ondan sonraki argümanlar betiğe iletilir ve önünde betik adı yoksa ilk argüman betik dosyası olarak kullanılır. Bu yüzden node --no-warnings app.js --no-warnings komutunda ilk bayrak Node.js'e, ikincisi uygulamanıza gider.
parseArgs yardım metni üretir mi?
Hayır. Belgedeki API seçenekleri ayrıştırır ve hatalı kullanımda hata fırlatır; kullanım ve yardım metnini kendiniz yazmanız gerekir.
Ctrl+C ile kapanırken temizlik nasıl yapılır?
Sinyal olayları ve sunucuların düzgün kapatılması cluster ve PM2 yazısında ele alınıyor. Sinyalle sonlanan süreçlerin çıkış kodu 128 artı sinyal numarasıdır.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Node.js öğrenme rehberi · Betik çalıştırma · process.env ve --env-file · readline ile girdi · uncaughtException · child_process · console ve stdout