Skrip bebas shell dengan Execa 7

Mar 12 2023
Meskipun skrip shell sangat berguna, banyak developer menikmati fleksibilitas, ekspresif, dan ekosistem yang disertakan dengan bahasa pemrograman seperti JavaScript. zx, proyek populer terbaru dari Google, menggabungkan yang terbaik dari kedua dunia.
Pantai yang hampir bebas kerang (foto oleh Aaron Burden)

Meskipun skrip shell sangat berguna, banyak developer menikmati fleksibilitas, ekspresif, dan ekosistem yang disertakan dengan bahasa pemrograman seperti JavaScript. zx, proyek populer terbaru dari Google, menggabungkan yang terbaik dari kedua dunia.

const branch = await $`git branch --show-current`
await $`deploy --branch=${branch}`

import { $ } from 'execa'

const branch = await $`git branch --show-current`
await $`deploy --branch=${branch}`

Mengapa menggunakan Node dan Bash? Dengan Execa, tidak ada sintaks shell yang perlu diingat: semuanya hanyalah JavaScript biasa. Hampir semua fitur khusus shell dapat diekspresikan dalam JavaScript. Untuk kasing edge yang tersisa, shellopsi tersedia.

Ini lebih:

  • Aman : injeksi shell secara teknis tidak layak.
  • Cross-platform : tidak semua mesin Windows menyediakan Bash.
  • Performant : menelurkan shell untuk setiap perintah harus dibayar mahal. Bahkan npxdapat dilewati karena Execa dapat langsung mengeksekusi binari yang diinstal secara lokal.
  • # In Bash
    API_KEY="secret" npx deploy "$cluster" &> logs.txt && echo "done"
    // In JavaScript
    import { $ } from 'execa'
    
    const options = { env: { API_KEY: 'secret' } }
    await $(options)`deploy ${cluster}`.pipeAll(’logs.txt’)
    console.log('done')
    

import { $ } from 'execa'
import pRetry from 'p-retry'

await pRetry(
  async () => await $`deploy dev_cluster`,
  { retries: 5 },
)

Modul child_processNode inti mencakup banyak fitur berguna: batas waktu, pembatalan, proses latar belakang , IPC , PID , UID/GID, referensi lemah , dan banyak lagi. Execa menambahkan beberapa tambahan : penghentian anggun , pembersihan , output interleaved , dll. Itu dapat diatur menggunakan $(options)salah satu atau beberapa perintah.

import { $ } from 'execa'

const $$ = $({ timeout: 5000, all: true })

// `all` retrieves both stdout and stderr
const { all } = $$`deploy dev_cluster`

Proses anak mungkin sulit untuk di-debug. Inilah mengapa Execa:

  • Termasuk verboseopsi , yang dapat diatur menggunakan NODE_DEBUG=execa.
  • Melaporkan pesan kesalahan dan properti mendetail .
  • Murni tanpa kewarganegaraan, membuatnya mudah untuk mencari tahu apa direktori saat ini, atau opsi lainnya.
  • > NODE_DEBUG=execa node deploy.js
    
    [16:50:03.305] deploy dev_cluster
    ........dev_cluster successfully deployed.
    
    [16:53:06.378] deploy prod_cluster
    .............prod_cluster successfully deployed.
    

import { $ } from 'execa'

// Pipe input from a string or buffer, like <<< in Bash
await $({ input: 'dev_cluster' })`deploy`

// Pipe input from a file, like < in Bash
await $({ inputFile: 'clusters.txt' })`deploy`

// Pipe output to a file, like >, 2> and &> in Bash
await $`deploy dev_cluster`.pipeStdout('stdout.txt')
await $`deploy dev_cluster`.pipeStderr('stderr.txt')
await $({ all: true })`deploy dev_cluster`.pipeAll('logs.txt')

// Pipe output to another command, like | and |& in Bash
await $`deploy dev_cluster`.pipeStdout($`grep done`)

// Pipe output to a stream, like 2>&1 in Bash
const { stdout } = await $`deploy dev_cluster`.pipeStderr(process.stdout)