Saya bertanya-tanya bagaimana aplikasi pembunuh seperti Thunderbird atau Firefox dapat diperbarui melalui manajer paket sistem saat mereka masih berjalan. Apa yang terjadi dengan kode lama ketika sedang diperbarui? Apa yang harus saya lakukan ketika saya ingin menulis sebuah program a.out yang memperbarui sendiri saat sedang berjalan?
files
upgrade
executable
ubuplex
sumber
sumber
Jawaban:
Mengganti file secara umum
Pertama, ada beberapa strategi untuk mengganti file:
Buka file yang ada untuk ditulis, potong hingga 0 panjang, dan tulis konten baru. (Varian yang kurang umum adalah membuka file yang ada, menimpa konten lama dengan konten baru, memotong file ke panjang baru jika lebih pendek.) Dalam istilah shell:
Hapus file lama, dan buat file baru dengan nama yang sama. Dalam istilah shell:
Tulis ke file baru dengan nama sementara, lalu pindahkan file baru ke nama yang ada. Langkah ini menghapus file lama. Dalam istilah shell:
Saya tidak akan mencantumkan semua perbedaan antara strategi, saya hanya akan menyebutkan beberapa yang penting di sini. Dengan stategy 1, jika ada proses saat ini menggunakan file, proses melihat konten baru saat sedang diperbarui. Ini dapat menyebabkan beberapa kebingungan jika proses mengharapkan konten file tetap sama. Perhatikan bahwa ini hanya tentang proses yang membuka file (seperti terlihat di dalam
lsof
atau di ; aplikasi interaktif yang memiliki dokumen terbuka (misalnya membuka file di editor) biasanya tidak membuat file tetap terbuka, mereka memuat konten file selama Operasi "buka dokumen" dan mereka mengganti file (menggunakan salah satu strategi di atas) selama operasi "simpan dokumen"./proc/PID/fd/
Dengan strategi 2 dan 3, jika beberapa proses
somefile
membuka file , file lama tetap terbuka selama peningkatan konten. Dengan strategi 2, langkah menghapus file sebenarnya hanya menghapus entri file di direktori. File itu sendiri hanya dihapus ketika tidak memiliki entri direktori yang mengarah ke sana (pada sistem file Unix khas, mungkin ada lebih dari satu entri direktori untuk file yang sama ) dan tidak ada proses yang terbuka. Inilah cara untuk mengamati ini - file hanya dihapus ketikasleep
prosesnya dimatikan (rm
hanya menghapus entri direktori-nya).Dengan strategi 3, langkah memindahkan file baru ke nama yang ada menghapus entri direktori yang mengarah ke konten lama dan membuat entri direktori yang mengarah ke konten baru. Ini dilakukan dalam satu operasi atom, jadi strategi ini memiliki keuntungan besar: jika suatu proses membuka file kapan saja, ia akan melihat konten lama atau konten baru - tidak ada risiko mendapatkan konten campuran atau file tidak ada.
Mengganti executable
Jika Anda mencoba strategi 1 dengan executable yang berjalan di Linux, Anda akan mendapatkan kesalahan.
“File teks” berarti file yang berisi kode yang dapat dieksekusi untuk alasan historis yang tidak jelas . Linux, seperti banyak varian unix lainnya, menolak untuk menimpa kode program yang sedang berjalan; beberapa varian unix memungkinkan ini, menyebabkan crash kecuali kode baru itu modifikasi yang sangat baik dari kode lama.
Di Linux, Anda dapat menimpa kode perpustakaan yang dimuat secara dinamis. Kemungkinan akan menyebabkan crash pada program yang menggunakannya. (Anda mungkin tidak dapat mengamati ini dengan
sleep
karena memuat semua kode perpustakaan yang dibutuhkan ketika dimulai. Cobalah program yang lebih kompleks yang melakukan sesuatu yang berguna setelah tidur, misalnyaperl -e 'sleep 9; print lc $ARGV[0]'
.)Jika penerjemah menjalankan skrip, file skrip dibuka dengan cara biasa oleh penerjemah, sehingga tidak ada perlindungan terhadap penulisan ulang skrip. Beberapa penerjemah membaca dan mem-parsing seluruh skrip sebelum mereka mulai mengeksekusi baris pertama, yang lain membaca skrip sesuai kebutuhan. Lihat Apa yang terjadi jika Anda mengedit skrip selama eksekusi? dan Bagaimana Linux menangani skrip shell? untuk lebih jelasnya.
Strategi 2 dan 3 juga aman untuk executable: walaupun menjalankan executable (dan perpustakaan yang dimuat secara dinamis) tidak membuka file dalam arti memiliki deskriptor file, mereka berperilaku dengan cara yang sangat mirip. Selama beberapa program menjalankan kode, file tetap di disk bahkan tanpa entri direktori.
Memutakhirkan aplikasi
Sebagian besar manajer paket menggunakan strategi 3 untuk mengganti file, karena keunggulan utama yang disebutkan di atas - kapan saja, membuka file mengarah ke versi yang valid.
Di mana pemutakhiran aplikasi dapat rusak adalah bahwa sementara memutakhirkan satu file bersifat atomik, memutakhirkan aplikasi secara keseluruhan tidak terjadi jika aplikasi terdiri dari banyak file (program, perpustakaan, data, ...). Pertimbangkan urutan kejadian berikut:
Pada langkah 3, instance berjalan dari versi lama aplikasi membuka file data dari versi baru. Apakah ini berfungsi atau tidak tergantung pada aplikasi, dari file mana itu dan seberapa banyak file tersebut telah dimodifikasi.
Setelah peningkatan, Anda akan perhatikan bahwa program lama masih berjalan. Jika Anda ingin menjalankan versi baru, Anda harus keluar dari program lama dan menjalankan versi baru. Manajer paket biasanya membunuh dan memulai ulang daemon pada pembaruan, tetapi membiarkan aplikasi pengguna akhir saja.
Beberapa daemon memiliki prosedur khusus untuk menangani peningkatan tanpa harus mematikan daemon dan menunggu instance baru untuk restart (yang menyebabkan gangguan layanan). Ini diperlukan dalam kasus init , yang tidak dapat dibunuh; sistem init menyediakan cara untuk meminta panggilan instance yang berjalan
execve
untuk menggantikan dirinya dengan versi baru.sumber
unlink
, seperti yang Anda bahas nanti. Mungkin "mengganti nama yang ada", tapi itu masih agak membingungkan.Pembaruan dapat dijalankan saat program berjalan, tetapi program yang berjalan yang Anda lihat sebenarnya adalah versi lama. Biner lama tetap di disk sampai Anda menutup program.
Penjelasan: pada sistem Linux, file hanyalah sebuah inode, yang dapat memiliki beberapa tautan. Misalnya. yang
/bin/bash
Anda lihat hanyalah tautan keinode 3932163
sistem saya. Anda dapat menemukan inode mana yang melakukan tautan ke sesuatu dengan menerbitkanls --inode /path
tautan tersebut. File (inode) hanya dihapus jika tidak ada tautan yang mengarah ke sana dan tidak digunakan oleh program apa pun. Ketika pengelola paket melakukan upgrade, mis./usr/bin/firefox
, pertama-tama menghapus tautan (menghapus tautan keras/usr/bin/firefox
), kemudian membuat file baru bernama/usr/bin/firefox
hardlink ke inode yang berbeda (yang berisifirefox
versi baru ). Inode lama sekarang ditandai sebagai bebas dan dapat digunakan kembali untuk menyimpan data baru tetapi tetap pada disk (inode hanya dibuat ketika Anda membangun sistem file Anda dan tidak pernah dihapus). Di awal berikutnyafirefox
, yang baru akan digunakan.Jika Anda ingin menulis sebuah program yang "memutakhirkan" dirinya saat berjalan, satu-satunya solusi yang dapat saya pikirkan adalah dengan memeriksa secara berkala stempel waktu file binernya sendiri, dan jika itu lebih baru daripada waktu mulai program, kemudian muat ulang.
sumber
apt
Pekerjaan peningkatan Debian ? Saya dapat memutakhirkan program yang sedang berjalan tanpa masalah termasukIceweasel
(Firefox
).dpkg
) tidak menimpa file. Alih-alih memutuskan tautan mereka dan menempatkan yang baru di bawah nama yang sama. Lihat pertanyaan & jawaban yang saya tautkan untuk penjelasan.ln
(tautan keras). Anda dapat menghapus nama denganrm
(batalkan tautan). Anda sebenarnya tidak bisa langsung menghapus file, hanya menghapus namanya. Ketika sebuah file tidak memiliki nama dan tambahan tidak terbuka, kernel akan menghapusnya. Program yang sedang berjalan memiliki file yang dijalankannya dari buka, jadi bahkan setelah menghapus semua nama, file tersebut masih ada.Saya ingin tahu bagaimana aplikasi pembunuh seperti Thunderbird atau Firefox dapat diperbarui melalui manajer paket sistem ketika masih berjalan? Yah, saya dapat memberi tahu Anda bahwa ini tidak benar-benar berfungsi dengan baik ... Firefox saya rusak cukup parah jika dibiarkan terbuka saat pembaruan paket sedang berjalan. Saya kadang-kadang harus membunuhnya dengan paksa dan menyalakannya kembali, karena sangat rusak sehingga saya bahkan tidak bisa menutupnya dengan benar.
Apa yang terjadi dengan kode lama ketika sedang diperbarui? Biasanya di Linux suatu program dimuat ke dalam memori, sehingga executable pada disk tidak diperlukan atau digunakan saat program sedang berjalan. Bahkan Anda bahkan dapat menghapus file yang dapat dieksekusi dan program tidak perlu ... Namun, beberapa program mungkin memerlukan file yang dapat dieksekusi, dan OS tertentu (seperti Windows) akan mengunci file yang dapat dieksekusi, mencegah penghapusan atau bahkan mengubah nama / memindahkan, sedangkan program sedang berjalan. Firefox rusak, karena sebenarnya cukup rumit dan menggunakan banyak file data yang memberi tahu cara membangun GUI (antarmuka pengguna). Selama paket pembaruan, file-file ini ditimpa (diperbarui), jadi ketika Firefox yang lebih lama dapat dieksekusi (dalam memori) mencoba menggunakan file GUI baru, hal-hal aneh dapat terjadi ...
Apa yang harus saya lakukan ketika saya ingin menulis sebuah program a.out yang memperbarui sendiri saat sedang berjalan? Sudah banyak jawaban untuk pertanyaan Anda. Lihat ini: /programming/232347/how-should-i-implement-an-auto-updater By the way, pertanyaan tentang pemrograman lebih baik di StackOverflow.
sumber