Program Unix / Linux tipikal menerima input baris perintah sebagai jumlah argumen ( int argc
) dan vektor argumen ( char *argv[]
). Elemen pertama argv
adalah nama program - diikuti oleh argumen aktual.
Mengapa nama program diteruskan ke executable sebagai argumen? Apakah ada contoh program menggunakan nama mereka sendiri (mungkin semacam exec
situasi)?
command-line
c
arguments
Shrikant Giridhar
sumber
sumber
sh
adalah symlink kedash
. Mereka berperilaku berbeda, ketika dipanggil sebagaish
atau sebagaidash
busybox
(umum pada disk-penyelamatan dan semacamnya), maka hampir semuanya (cp, mv, rm, ls, ...) adalah tautan simbolis ke busybox.gcc
,bash
,gunzip
, sebagian besar sisa dari OS ...), Linux hanya kernel.Jawaban:
Untuk mulai dengan, perhatikan bahwa
argv[0]
tidak harus nama program. Ini adalah apa pemanggil menempatkan keargv[0]
dariexecve
system call (misalnya lihat pertanyaan ini pada Stack Overflow ). (Semua varian lainexec
bukan pemanggilan sistem tetapi antarmuka untukexecve
.)Misalkan, misalnya, yang berikut (menggunakan
execl
):/var/tmp/mybackdoor
adalah apa yang dieksekusi tetapiargv[0]
diatur ketop
, dan ini adalah apaps
yangtop
akan ditampilkan. Lihat jawaban ini di U&L SE untuk informasi lebih lanjut tentang ini.Mengesampingkan semua ini: Sebelum munculnya filesystem mewah seperti
/proc
,argv[0]
adalah satu-satunya cara bagi proses untuk belajar tentang namanya sendiri. Apa gunanya itu?sumber
bunzip2
,bzcat
danbzip2
, untuk yang pertama adalah symlink ke yang ketiga.zcat
bukan symlink. Mereka tampaknya menghindari kelemahan dari teknik ini menggunakan skrip shell sebagai gantinya. Tetapi mereka gagal mencetak--help
keluaran lengkap karena seseorang yang menambahkan opsi ke gzip lupa untuk memelihara zcat juga.gunzip
adalah pengecualian historis.argv[0]
dalam penggunaan / bantuan keluaran mereka daripada meng-coding nama mereka. Beberapa secara penuh, beberapa hanya nama samaran.Banyak:
argv[0]
inish
. Ini berjalan sebagai shell login ketikaargv[0]
dimulai dengan-
.vi
,view
,evim
,eview
,ex
,vimdiff
, dllshutdown
,reboot
, dll symlink untuksystemctl
.sumber
sendmail
danmail
. Setiap MTA unix tunggal hadir dengan symlink untuk dua perintah tersebut, dan dirancang untuk meniru perilaku asli ketika dipanggil, yang berarti bahwa setiap program unix yang perlu mengirim email tahu persis bagaimana mereka dapat melakukannya.test
dan[
: ketika Anda memanggil yang pertama, ia menangani kesalahan jika argumen terakhir adalah]
. (pada stabil Debian aktual, perintah ini adalah dua program yang berbeda, tetapi versi sebelumnya dan MacO masih menggunakan program yang sama). Dantex
,latex
dan seterusnya: binernya sama, tetapi melihat bagaimana namanya, ia memilih file konfigurasi yang tepat .init
serupa.[
menganggapnya sebagai kesalahan jika argumen terakhir tidak]
.Secara historis,
argv
hanyalah array pointer ke "kata-kata" dari commandline, jadi masuk akal untuk memulai dengan "kata" pertama, yang kebetulan merupakan nama program.Dan ada beberapa program yang berperilaku berbeda sesuai dengan nama yang digunakan untuk memanggil mereka, jadi Anda bisa membuat tautan berbeda ke mereka dan mendapatkan "perintah" yang berbeda. Contoh paling ekstrem yang bisa saya pikirkan adalah busybox , yang bertindak seperti beberapa lusin "perintah" yang berbeda tergantung bagaimana namanya .
Sunting : Referensi untuk Unix edisi 1, seperti yang diminta
Orang dapat melihat misalnya dari fungsi utama
cc
ituargc
danargv
sudah digunakan. The shell salinan argumen keparbuf
dalamnewarg
bagian dari loop, sementara memperlakukan perintah itu sendiri dalam cara yang sama seperti argumen. (Tentu saja, nanti hanya menjalankan argumen pertama, yang merupakan nama perintah). Sepertinyaexecv
dan kerabat tidak ada saat itu.sumber
exec
mengambil nama dari perintah untuk mengeksekusi dan array nol-dihentikan pointer char (terbaik dilihat di minnie.tuhs.org/cgi-bin/utree.pl?file=V1/u0.s , di manaexec
dibutuhkan referensi ke label 2 dan label 1, dan pada label2:
munculetc/init\0
, dan pada label1:
muncul referensi ke label 2, dan berakhir nol), yang pada dasarnya adalah apa yangexecve
dikurangi hari inienvp
.execv
danexecl
telah ada "selamanya" (yaitu, sejak awal hingga pertengahan 1970-an) -execv
adalah panggilan sistem danexecl
fungsi perpustakaan yang menyebutnya.execve
tidak ada karena lingkungan tidak ada. Anggota keluarga lainnya ditambahkan kemudian.execv
sumber v1 yang saya tautkan? Hanya penasaran.Gunakan kasing:
Anda dapat menggunakan nama program untuk mengubah perilaku program .
Misalnya Anda bisa membuat beberapa symlink ke biner yang sebenarnya.
Salah satu contoh terkenal di mana teknik ini digunakan adalah proyek busybox yang menginstal hanya satu biner tunggal dan banyak symlink ke sana. (ls, cp, mv, dll). Mereka melakukannya untuk menghemat ruang penyimpanan karena target mereka adalah perangkat tertanam kecil.
Ini juga digunakan di
setarch
dari util-linux:Di sini mereka menggunakan teknik ini pada dasarnya untuk menghindari banyak file sumber duplikat atau hanya agar sumbernya lebih mudah dibaca.
Kasus penggunaan lain adalah program yang perlu memuat beberapa modul atau data saat runtime. Memiliki jalur program membuat Anda dapat memuat modul dari jalur relatif ke lokasi program .
Apalagi banyak program mencetak pesan kesalahan termasuk nama program .
Mengapa :
man 3p execve
):Perhatikan Standar C mengatakan "nama program" bukan "nama file".
sumber
Selain program yang mengubah perilaku mereka tergantung pada bagaimana mereka dipanggil, saya merasa
argv[0]
berguna dalam mencetak penggunaan suatu program, seperti:Ini menyebabkan pesan penggunaan selalu menggunakan nama yang digunakan untuk memanggilnya. Jika program diubah namanya, pesan penggunaannya akan berubah. Bahkan termasuk nama jalur yang dipanggil dengan:
Ini adalah sentuhan yang bagus, terutama untuk alat / skrip bertujuan kecil yang mungkin tinggal di mana-mana.
Ini sepertinya praktik umum dalam alat GNU juga, lihat
ls
misalnya:sumber
Satu mengeksekusi program mengetik:
program_name0 arg1 arg2 arg3 ...
.Jadi shell seharusnya sudah membagi token, dan token pertama sudah menjadi nama program. Dan BTW jadi ada indeks yang sama di sisi program dan di shell.
Saya pikir ini hanya trik yang mudah (pada awalnya), dan, seperti yang Anda lihat di jawaban lain, itu juga sangat berguna, sehingga tradisi ini dilanjutkan dan ditetapkan sebagai API.
sumber
Pada dasarnya, argv menyertakan nama program sehingga Anda dapat menulis pesan kesalahan seperti
prgm: file: No such file or directory
, yang akan diimplementasikan dengan sesuatu seperti ini:sumber
Contoh lain dari aplikasi ini adalah program ini, yang menggantikan dirinya dengan ... itu sendiri, sampai Anda mengetik sesuatu yang tidak
y
.Jelas, semacam contoh menarik jika dibuat, tapi saya pikir ini mungkin memiliki kegunaan nyata - misalnya, biner memperbarui diri, yang menulis ulang ruang memori sendiri dengan versi baru sendiri yang diunduh atau diubah.
Contoh:
Sumber, dan beberapa info lainnya .
sumber
Path ke program adalah
argv[0]
, sehingga program dapat mengambil file konfigurasi dll dari direktori instalnya.Ini tidak mungkin tanpa
argv[0]
.sumber
(char *path_to_program, char **argv, int argc)
misalnya~/.<program>
,/etc/<program
,$XDG_CONFIG_HOME
) dan baik mengambil parameter untuk mengubah atau memiliki pilihan kompilasi yang bakes dalam konstan untuk biner.ccache berperilaku seperti ini untuk meniru panggilan berbeda ke kompiler binari. ccache adalah kompilasi cache - seluruh intinya tidak pernah mengkompilasi kode sumber yang sama dua kali tetapi sebaliknya mengembalikan kode objek dari cache jika memungkinkan.
Dari halaman manual ccache , "ada dua cara untuk menggunakan ccache. Anda dapat mengawali perintah kompilasi dengan ccache atau Anda dapat membiarkan ccache menyamar sebagai kompiler dengan membuat tautan simbolis (dinamai sebagai kompiler) ke ccache. Metode pertama lebih nyaman jika Anda hanya ingin mencoba ccache atau ingin menggunakannya untuk beberapa proyek tertentu. Metode kedua paling berguna ketika Anda ingin menggunakan ccache untuk semua kompilasi Anda. "
Metode symlinks melibatkan menjalankan perintah-perintah ini:
... efeknya adalah memungkinkan ccache untuk mengambil perintah apa pun yang seharusnya pergi ke kompiler, sehingga memungkinkan ccache untuk mengembalikan file yang di-cache atau meneruskan perintah ke kompiler yang sebenarnya.
sumber