1 poin oleh GN⁺ 2 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • BusyBox adalah binary multicall yang menyediakan banyak perintah dalam satu berkas eksekusi, dan wget bawaan Alpine juga dijalankan melalui BusyBox
  • /usr/bin/wget pada kontainer Alpine bukan binary sebenarnya, melainkan tautan simbolik yang menunjuk ke /bin/busybox
  • Saat dijalankan, BusyBox membaca nama panggilan dari argv[0] dan menentukan applet yang akan dijalankan berdasarkan nama terakhir pada path
  • Setiap applet dicari berdasarkan namanya lalu masuk ke fungsi main yang sesuai; wget diimplementasikan di wget.c dan pada akhirnya menjalankan wget_main
  • Perintah yang dikompilasi dapat dilihat dengan busybox --list, dan pada contoh Alpine ditampilkan 304 buah, dengan tiap utilitas tampak seperti versi yang diperkecil

Cara kerja BusyBox

  • BusyBox menggunakan struktur binary multicall (multicall binary) yang menyediakan banyak perintah dalam satu berkas eksekusi
  • Pada kontainer Alpine, /usr/bin/wget bukan berkas eksekusi sebenarnya, melainkan tautan simbolik yang menunjuk ke /bin/busybox
    docker run --rm -it alpine sh
    / # which wget
    /usr/bin/wget
    / # ls -lah /usr/bin/wget
    lrwxrwxrwx    1 root     root          12 Apr 15 04:51 /usr/bin/wget -> /bin/busybox
    
  • Di /usr/bin tampak lebih dari 130 berkas eksekusi yang sebenarnya berasal dari satu binary yang sama, dan ini terkait dengan struktur binary multicall BusyBox
  • Saat dijalankan, BusyBox mengambil nama yang dipanggil dari argv[0], lalu hanya mengambil nama terakhir dari path untuk menentukan applet mana yang harus dijalankan
    applet_name = argv[0];
    if (applet_name[0] == '-')
      applet_name++;
    applet_name = bb_basename(applet_name);
    
  • BusyBox juga bisa berjalan jika nama applet diberikan secara eksplisit seperti busybox ls -1, dan jika nama yang diberikan tidak ada maka akan muncul applet not found
    / # busybox ls -1
    bin
    dev
    etc
    home
    
    / # busybox meheh
    meheh: applet not found
    

Struktur applet dan cara pemasangan

  • BusyBox mencari applet berdasarkan namanya lalu menjalankan fungsi main milik applet tersebut
    int applet = find_applet_by_name(name);
    // ...
    run_applet_no_and_exit(applet, name, argv);
    // ...
    xfunc_error_retval = applet_main[applet_no](argc, argv);
    
  • Setiap applet memiliki berkas C terpisah, dan wget diimplementasikan di wget.c
  • Konfigurasi per applet didefinisikan dalam bentuk komentar kode; pada pengaturan WGET terdapat wget (41 kb), aktif secara default, bantuan yang menjelaskan utilitas untuk mengunduh file secara non-interaktif dari server HTTP dan FTP, serta target build wget.o
    //config:config WGET
    //config:	bool "wget (41 kb)"
    //config:	default y
    //config:	help
    //config:	wget is a utility for non-interactive download of files from HTTP
    //config:	and FTP servers.
    //applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
    //kbuild:lib-$(CONFIG_WGET) += wget.o
    
  • Pada akhirnya, applet wget masuk ke wget_main
    int wget_main(int argc UNUSED_PARAM, char **argv)
    
  • BusyBox juga mendukung hard link, dan pada busybox --install -s, -s berarti membuat tautan simbolik
    busybox --install -s
    
  • Daftar perintah yang disertakan dalam hasil kompilasi dapat dilihat dengan busybox --list, dan pada lingkungan contoh Alpine ditampilkan 304 buah
    / # busybox --list | wc -l
    304
    
  • Banyak perintah di Alpine bekerja seperti antarmuka ke binary berbasis BusyBox, dan masing-masing utilitas tampak seperti versi yang diperkecil dibanding utilitas asli yang lengkap

1 komentar

 
GN⁺ 2 jam lalu
Pendapat di Lobste.rs
  • Jawaban untuk pertanyaan yang dikutip lebih dekat ke implementasi ulang
    Perkenalan BusyBox ada di https://busybox.net/about.html, dan sumbernya ada di https://github.com/vda-linux/busybox_mirror

  • Cukup mengganggu ketika sebuah program berpura-pura memakai nama yang berbeda dari yang sebenarnya
    Kasus terburuk adalah saat menjalankan gcc di macOS tetapi yang sebenarnya muncul adalah clang, dan PowerShell juga bekerja dengan cara yang mirip. Akan lebih baik kalau memakai nama yang berbeda saja

    • Sebagian ini juga masalah yang muncul karena dimulai pada masa ketika banyak pengembang tidak mengenal clang, tidak punya Mac untuk menguji, atau tidak punya alternatif yang realistis
      Nixpkgs harus membuat banyak patch seperti https://github.com/NixOS/nixpkgs/…, dan bahkan proyek terkenal seperti sqlite bukan pengecualian. Sebaliknya, macOS pada dasarnya memilih jalur menipu lewat path
    • Ada orang yang menulis makefile untuk banyak perangkat lunak tetapi tidak mengenal cc
    • Saya paham rasa frustrasinya, tetapi kemungkinan ini menyebar karena selama cukup kompatibel untuk menjalankan sebagian besar skrip build, skrip yang sama bisa dipakai ulang sampai batas tertentu di Linux dan berbagai keluarga Unix lainnya
    • Kadang memang tidak memungkinkan secara praktis
      Mungkin ada banyak makefile yang meng-hardcode gcc, dan hal serupa juga terjadi di konteks lain. Misalnya, karena banyak program yang ada memeriksa xterm-* pada variabel lingkungan TERM alih-alih basis data terminfo yang merupakan solusi yang benar, memilih nama lain tidak berhasil
  • Saat mendiagnosis masalah aneh di container, saya sering memakai podman cp /usr/bin/busybox-static somecontainer:/bin

  • toybox juga punya struktur yang mirip
    Beberapa alat tampaknya diambil atau diport dari tempat lain, tetapi cukup banyak yang diimplementasikan baru untuk BusyBox, dengan tujuan menjaga ukurannya kecil dan hanya memakai fitur libc yang terbatas agar hasil kompilasi tetap kecil saat static linking. Keuntungan lain adalah alat-alat ini bisa dipakai dari skrip shell seperti perintah bawaan. Sebagian dijalankan dengan fork+jump alih-alih fork+exec, dan beberapa bahkan bisa dijalankan tanpa fork, cukup sebagai pemanggilan fungsi biasa

    • Setahu saya toybox awalnya dibuat sebagai alternatif berlisensi BSD untuk BusyBox yang berlisensi GPL
      Tambahan, menurut Toybox di Wikipedia, “Toybox dimulai pada awal 2006 setelah Rob Landley berhenti menjadi pemelihara BusyBox akibat perselisihan dengan Bruce Perens, pembuat asli BusyBox”
  • Secara praktik ini memang implementasi ulang. Meski begitu, kalau lisensinya mengizinkan, tidak akan mengejutkan bila sebagian kode dipinjam dari implementasi besar yang asli
    Menurut dari 'pedia: BusyBox pertama kali ditulis oleh Bruce Perens pada 1995, dan pada 1996 dinyatakan selesai untuk tujuan awalnya. Target awalnya adalah menempatkan sistem lengkap yang bisa boot ke dalam satu disket, yang berfungsi sebagai disk pemulihan dan penginstal untuk distribusi Debian. Setelah itu, ia berkembang menjadi kumpulan alat inti user-space yang secara de facto menjadi standar untuk perangkat Linux embedded dan penginstal distribusi Linux, dan karena setiap executable Linux membutuhkan overhead beberapa KB, menggabungkan lebih dari 200 program menjadi satu bisa sangat menghemat ruang disk dan memori
    Terkait itu, Toybox juga punya struktur dan filosofi yang serupa, tetapi berlisensi BSD. Saya ingat pengembang utamanya, Rob Landley, melihat bahwa lisensi yang lebih mudah diterima secara komersial bisa membuatnya dimasukkan ke perangkat Android, dan kalau itu terjadi maka semua ponsel dan tablet Android berpotensi berubah menjadi lingkungan pengembangan mirip Unix. Toybox tampaknya masih menjadi bagian dari Android, tetapi tanpa alat lapisan atas yang membantu seperti Termux, Android tetap tidak mudah dipakai seperti Unix

    • Sulit membayangkan contoh yang lebih sempurna sebagai kasus textbook tentang bagaimana memberi tenaga kerja gratis kepada perusahaan seperti Google bisa berbalik merugikan diri sendiri
      Terlebih jika mengingat bahwa Google selama bertahun-tahun mengancam akan memblokir Termux
  • Ada juga port untuk Windows: https://github.com/rmyorston/busybox-w32
    Ukuran BusyBox yang kecil membuat port seperti ini lebih realistis. Namun sekarang orang bisa langsung menjalankan Linux di dalam Windows, jadi relevansinya tampaknya agak berkurang