Setelah executable dihasilkan oleh linker, tugas berikutnya adalah menjalankannya dengan benar. Cara kita menjalankan executable menentukan apakah program menerima argumen, ke mana keluaran ditujukan, dan kode apa yang dikembalikan ke sistem operasi. Pada Chapter ini kita akan mempelajari cara menjalankan executable C di Linux, mengakses argumen command line, memeriksa exit code, serta memisahkan standard output dan standard error.

Menjalankan Executable Dasar #

Cara paling sederhana menjalankan executable di Linux adalah dengan memanggil nama file-nya beserta prefiks ./ bila berada di direktori kerja saat ini:

c
#include <stdio.h>

int main(void) {
    printf("Halo dari program C.\n");
    return 0;
}

Simpan sebagai halo.c, kompilasi, lalu jalankan:

bash
gcc -std=c11 -Wall -Wextra -o halo halo.c
./halo
echo $?

Output yang Dihasilkan:

text
Halo dari program C.
0

Mari kita telaah baris-baris perintah di atas:

  1. ./halo: shell menjalankan executable halo di direktori saat ini; prefiks ./ diperlukan karena Linux tidak mencari executable di direktori kerja saat ini secara default.
  2. echo $?: variabel khusus $? menyimpan exit code dari perintah terakhir; nilai 0 berarti program berakhir sukses.

Argumen Command Line #

Banyak program C menerima argumen command line. Untuk mengakses argumen ini, fungsi main harus dideklarasikan dengan dua parameter: int argc (jumlah argumen) dan char *argv[] (array string argumen).

c
#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("Jumlah argumen : %d\n", argc);
    for (int i = 0; i < argc; i++) {
        printf("  argv[%d] = %s\n", i, argv[i]);
    }
    return 0;
}

Jalankan tanpa argumen tambahan:

bash
./args

Output yang Dihasilkan:

text
Jumlah argumen : 1
  argv[0] = ./args

Jalankan dengan beberapa argumen:

bash
./args --nama Budi --umur 17

Output yang Dihasilkan:

text
Jumlah argumen : 5
  argv[0] = ./args
  argv[1] = --nama
  argv[2] = Budi
  argv[3] = --umur
  argv[4] = 17

Mari kita telaah baris-baris kode di atas:

  1. Baris 3 (int main(int argc, char *argv[])): tanda tangan main yang menerima argumen command line; argc menyimpan jumlah argumen, argv adalah array pointer ke string argumen.
  2. Baris 5 (printf("Jumlah argumen : %d\n", argc);): mencetak jumlah argumen; argumen selalu minimal 1 karena argv[0] berisi nama program itu sendiri.
  3. Baris 6 (for (int i = 0; i < argc; i++)): loop dari 0 hingga argc - 1, mencetak setiap argumen.
  4. Baris 7 (argv[i]): setiap elemen argv adalah string C (array char diakhiri null); %s mencetaknya.

Exit Code sebagai Sinyal Status #

Fungsi main mengembalikan nilai int ke sistem operasi. Nilai ini disebut exit code atau exit status. Konvensi POSIX menyatakan 0 berarti sukses, sementara nilai 1 sampai 255 menandakan berbagai jenis kegagalan.

c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    printf("Pesan ke stdout\n");
    fprintf(stderr, "Pesan ke stderr\n");
    return 42;
}

Kompilasi lalu jalankan, periksa exit code segera setelah program selesai:

bash
gcc -std=c11 -Wall -Wextra -o keluaran keluaran.c
./keluaran
echo "exit code: $?"

Output yang Dihasilkan:

text
Pesan ke stdout
Pesan ke stderr
exit code: 42

Mari kita telaah baris-baris kode di atas:

  1. Baris 6 (printf("Pesan ke stdout\n");): menulis ke standard output (file descriptor 1), yang biasanya terhubung ke terminal.
  2. Baris 7 (fprintf(stderr, "Pesan ke stderr\n");): menulis ke standard error (file descriptor 2), juga terhubung ke terminal secara default namun merupakan aliran terpisah dari stdout.
  3. Baris 8 (return 42;): mengembalikan 42 ke sistem operasi; nilai ini bisa diperiksa lewat variabel $? di shell.

Perlu diingat bahwa nilai exit code yang valid hanya 0 sampai 255. Bila program mengembalikan nilai di luar rentang tersebut (misalnya -1 atau 256), shell akan melakukan modulo 256 dan nilai yang terlihat bisa berbeda dari yang dikembalikan program.

Memisahkan stdout dan stderr #

Standard output dan standard error adalah dua aliran terpisah. Saat menjalankan program, keduanya biasanya tampil di terminal secara tercampur. Kita bisa memisahkannya dengan redirection shell:

bash
./keluaran > stdout.txt 2> stderr.txt
echo "stdout.txt:"
cat stdout.txt
echo "stderr.txt:"
cat stderr.txt

Output yang Dihasilkan:

text
stdout.txt:
Pesan ke stdout
stderr.txt:
Pesan ke stderr

Operator > mengarahkan stdout ke file, sementara 2> mengarahkan stderr (file descriptor 2) ke file lain. Pemisahan ini sangat berguna saat kita ingin menyimpan output normal ke satu file dan pesan kesalahan ke file lain untuk analisis terpisah.

Menjalankan di Background dan dengan Pipe #

Untuk program yang berjalan lama, kita bisa menjalankannya di background dengan akhiran &:

bash
./program_lama &

Shell langsung mengembalikan kontrol ke kita sambil menjalankan program secara paralel. Perintah jobs menampilkan daftar background job, dan wait menunggu semua background job selesai.

Untuk mengirimkan output satu program sebagai input program lain, gunakan pipe |:

bash
./program_a | ./program_b

Program program_a berjalan sebagai penghasil output, dan program_b berjalan sebagai pembaca input. Kedua program berjalan secara konkuren, dengan output program_a mengalir ke input program_b.