GNU/Linux >> Belajar Linux >  >> Linux

Apa yang Terjadi Saat Saya Mengeksekusi File Di Shell?

Jadi, saya pikir saya memiliki pemahaman yang baik tentang ini, tetapi hanya menjalankan tes (sebagai tanggapan atas percakapan di mana saya tidak setuju dengan seseorang) dan menemukan bahwa pemahaman saya salah…

Sedetail mungkin apa yang sebenarnya terjadi ketika saya menjalankan file di shell saya? Yang saya maksud adalah, jika saya mengetik:./somefile some arguments ke dalam shell saya dan tekan kembali (dan somefile ada di cwd, dan saya telah membaca+mengeksekusi izin pada somefile ) lalu apa yang terjadi di balik tenda?

Saya pikir jawabannya adalah:

  1. Shell membuat panggilan sys ke exec , meneruskan jalur ke somefile
  2. Kernel memeriksa somefile dan melihat angka ajaib dari file untuk menentukan apakah itu format yang dapat ditangani oleh prosesor
  3. Jika angka ajaib menunjukkan bahwa file tersebut dalam format yang dapat dieksekusi oleh prosesor, maka
    1. proses baru dibuat (dengan entri di tabel proses)
    2. somefile dibaca/dipetakan ke memori. Tumpukan dibuat dan eksekusi melompat ke titik masuk kode somefile , dengan ARGV diinisialisasi ke array parameter (char** , ["some","arguments"] )
  4. Jika angka ajaib adalah shebang maka exec() memunculkan proses baru seperti di atas, tetapi eksekusi yang digunakan adalah penerjemah yang dirujuk oleh Shebang (mis. /bin/bash atau /bin/perl ) dan somefile diteruskan ke STDIN
  5. Jika file tidak memiliki angka ajaib yang valid, maka kesalahan seperti “file tidak valid (angka ajaib buruk):Kesalahan format Exec” terjadi

Namun seseorang memberi tahu saya bahwa jika file tersebut adalah teks biasa, maka Shell mencoba menjalankan perintah (seolah-olah saya telah mengetik bash somefile ). Saya tidak percaya ini, tetapi saya baru saja mencobanya, dan itu benar. Jadi saya jelas memiliki beberapa kesalahpahaman tentang apa yang sebenarnya terjadi di sini, dan ingin memahami mekanismenya.

Apa sebenarnya yang terjadi ketika saya menjalankan file di shell saya? (sedetail mungkin…)

Jawaban yang Diterima:

Jawaban pasti untuk "bagaimana program dijalankan" di Linux adalah sepasang artikel di LWN.net berjudul, cukup mengejutkan, Bagaimana program dijalankan dan Bagaimana program dijalankan:ELF biner. Artikel pertama membahas skrip secara singkat. (Tepatnya jawaban pasti ada di kode sumber, tetapi artikel ini lebih mudah dibaca dan menyediakan tautan ke kode sumber.)

Sebuah eksperimen kecil menunjukkan bahwa Anda cukup banyak melakukannya dengan benar, dan bahwa eksekusi file yang berisi daftar perintah sederhana, tanpa shebang, perlu ditangani oleh shell. Halaman manual execve(2) berisi kode sumber untuk program pengujian, execve; kita akan menggunakannya untuk melihat apa yang terjadi tanpa cangkang. Pertama, tulis skrip tes, testscr1 , berisi

#!/bin/sh

pstree

dan satu lagi, testscr2 , hanya berisi

pstree

Jadikan keduanya dapat dieksekusi, dan verifikasi bahwa keduanya dijalankan dari shell:

chmod u+x testscr[12]
./testscr1 | less
./testscr2 | less

Sekarang coba lagi, menggunakan execve (dengan asumsi Anda membuatnya di direktori saat ini):

./execve ./testscr1
./execve ./testscr2

testscr1 masih berjalan, tetapi testscr2 menghasilkan

execve: Exec format error

Ini menunjukkan bahwa shell menangani testscr2 berbeda. Itu tidak memproses skrip itu sendiri, masih menggunakan /bin/sh untuk melakukannya; ini dapat diverifikasi dengan mem-piping testscr2 menjadi less :

./testscr2 | less -ppstree

Di sistem saya, saya mendapatkan

    |-gnome-terminal--+-4*[zsh]
    |                 |-zsh-+-less
    |                 |     `-sh---pstree

Seperti yang Anda lihat, ada shell yang saya gunakan, zsh , yang dimulai dengan less , dan cangkang kedua, sh . biasa (dash di sistem saya), untuk menjalankan skrip, yang menjalankan pstree . Dalam zsh ini ditangani oleh zexecve di Src/exec.c :shell menggunakan execve(2) untuk mencoba menjalankan perintah, dan jika gagal, ia membaca file untuk melihat apakah ia memiliki Shebang, memprosesnya sesuai (yang juga akan dilakukan oleh kernel), dan jika gagal ia mencoba menjalankan file dengan sh , selama tidak membaca nol byte dari file:

        for (t0 = 0; t0 != ct; t0++)
            if (!execvebuf[t0])
                break;
        if (t0 == ct) {
            argv[-1] = "sh";
            winch_unblock();
            execve("/bin/sh", argv - 1, newenvp);
        }

bash memiliki perilaku yang sama, diimplementasikan di execute_cmd.c dengan komentar yang membantu (seperti yang ditunjukkan oleh taliezin):

Jalankan perintah sederhana yang mudah-mudahan didefinisikan dalam file disk
di suatu tempat.

  1. fork ()
  2. menghubungkan pipa
  3. cari perintahnya
  4. lakukan pengalihan
  5. execve ()
  6. Jika execve gagal, lihat apakah file memiliki mode yang dapat dieksekusi yang disetel.
    Jika demikian, dan itu bukan direktori, maka jalankan isinya sebagai
    skrip shell.

POSIX mendefinisikan satu set fungsi, yang dikenal sebagai exec(3) fungsi, yang membungkus execve(2) dan menyediakan fungsi ini juga; lihat jawaban muru untuk detailnya. Di Linux setidaknya fungsi-fungsi ini diimplementasikan oleh pustaka C, bukan oleh kernel.

Terkait:tujuan kata kunci "lakukan" di Bash untuk loop?
Linux
  1. tidak dapat mengeksekusi file biner saat mencoba menjalankan skrip shell di linux

  2. Apa yang terjadi ketika sebuah benang bercabang?

  3. Cara mengeksekusi file tanpa ekstensi .sh di shell

  1. Apa yang dilakukan izin eksekusi?

  2. Apa yang terjadi jika file yang 100% dimasukkan ke dalam cache halaman diubah oleh proses lain

  3. Apa bagian lengket dalam sistem file UNIX? Kapan digunakan?

  1. Deteksi Sistem Init Menggunakan Shell?

  2. Apa Yang Terjadi Saat Saya Menjalankan Perintah Cat /proc/cpuinfo?

  3. Apa shell default Busybox?