Bagaimana saya bisa mengelabui proses berpikir file tidak ada?

31

Saya memiliki program yang menyimpan pengaturannya di ~/.config/myprogramyang saya gunakan baik secara interaktif dan dengan sistem antrian batch. Saat berjalan secara interaktif, saya ingin program ini menggunakan file konfigurasi saya (dan memang demikian). Tetapi ketika menjalankan dalam mode batch, file konfigurasi tidak diperlukan karena saya menentukan opsi baris perintah yang menimpa semua pengaturan yang relevan. Selanjutnya, mengakses file konfigurasi melalui jaringan meningkatkan waktu startup program beberapa detik; jika file tidak ada, program diluncurkan lebih cepat (karena setiap pekerjaan hanya membutuhkan waktu sekitar satu menit, ini memiliki dampak signifikan pada throughput pekerjaan batch). Tetapi karena saya juga menggunakan program ini secara interaktif, saya tidak ingin memindahkan / menghapus file konfigurasi saya sepanjang waktu. Bergantung pada kapan pekerjaan batch saya dijadwalkan pada cluster (berdasarkan penggunaan pengguna lain),

(Selain itu: kinerja file jaringan sangat lambat mungkin adalah bug, tapi saya hanya pengguna cluster, jadi saya hanya bisa mengatasinya, tidak memperbaikinya.)

Saya bisa membuat versi program yang tidak membaca file konfigurasi (atau memiliki opsi baris perintah untuk tidak) untuk penggunaan batch, tetapi lingkungan build program ini tidak dirancang dengan baik dan sulit diatur. Saya lebih suka menggunakan binari yang diinstal melalui manajer paket sistem saya.

Bagaimana saya bisa mengelabui contoh tertentu dari program ini untuk berpura-pura file konfigurasi saya tidak ada (tanpa memodifikasi program)? Saya berharap untuk pembungkus formulir pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options..., tetapi saya terbuka untuk solusi lain.

Jeffrey Bosboom
sumber
2
Anda dapat menjalankannya sebagai pengguna yang tidak memiliki izin untuk membaca file.
psimon
1
@psimon Sebagai "hanya pengguna" dari kluster, saya tidak dapat membuat pengguna baru untuk menjalankan pekerjaan batch saya sebagai. Itu ide yang cerdas, dan jika tidak ada saran yang lebih baik, saya akan bug admin cluster untuk melakukannya untuk saya.
Jeffrey Bosboom
Atau atur skrip yang mengubah nama file konfigurasi terlebih dahulu, menjalankan program dan kemudian mengubah nama file konfigurasi lagi.
psimon
@psimon Saya kira saya bisa lebih jelas: Saya mungkin menggunakan program secara interaktif dan dalam mode batch pada saat yang sama, tergantung pada kapan pekerjaan batch saya dijadwalkan pada cluster.
Jeffrey Bosboom
1
Ya, jika terhubung secara dinamis, Anda dapat menggunakan LD_PRELOADpengait. Itu lebih mudah (Anda dapat mengimplementasikannya dalam satu atau dua jam, jika Anda tahu C) daripada alternatifnya, yaitu ptrace. Anda juga mungkin bisa menggunakan fakechroot untuk melakukan ini (saya yakin, itu adalah LD_PRELOAD).
derobert

Jawaban:

33

Program itu mungkin menyelesaikan jalur dari file itu $HOME/.config/myprogram. Jadi Anda bisa tahu direktori home Anda ada di tempat lain, seperti:

HOME=/nowhere your-program

Sekarang, mungkin program Anda membutuhkan sumber daya lain di direktori home Anda. Jika Anda tahu yang mana, Anda dapat menyiapkan rumah palsu untuk program Anda dengan tautan ke sumber yang dibutuhkan di sana.

mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram
Stéphane Chazelas
sumber
5
Jawaban ini menyelesaikan masalah saya, jadi saya menerimanya meskipun itu bukan jawaban yang sepenuhnya umum untuk pertanyaan dalam judul pertanyaan ini. Preload hook, seperti dijelaskan dalam jawaban lain, adalah solusi yang lebih umum (tetapi juga usaha yang lebih tinggi).
Jeffrey Bosboom
28

Jika semuanya gagal, tulis pustaka pembungkus yang akan Anda gunakan menggunakan injeksi LD_PRELOADsehingga panggilan untuk open("/home/you/my-program/config.interactive")dicegat tetapi yang lain akan melewati. Ini berfungsi untuk semua jenis program, bahkan skrip shell, karena akan menyaring panggilan sistem.

extern int errno;

int open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    return get_real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1;
  }
}

Catatan: Saya belum menguji kode ini, dan saya tidak 100% yakin bahwa errnobagian itu berfungsi.

Lihatlah bagaimana fakerootrasanya untuk panggilan getuid(2)dan stat(2).

Pada dasarnya, penghubung akan menautkan aplikasi itu ke perpustakaan Anda, yang mengabaikan opensimbol. Karena Anda tidak dapat menggunakan dua fungsi berbeda yang disebut opendi perpustakaan Anda sendiri, Anda harus memisahkannya di bagian kedua (misalnya get_real_open) yang pada gilirannya akan menghubungkan ke openpanggilan asli .

Asli: ./Application

Application -----> libc.so
            open()

Dicegat: LD_PRELOAD=yourlib_wrap.so ./Application

Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
            open()                 get_real_open()                 open()

Sunting: Rupanya ada ldbendera yang dapat Anda aktifkan ( --wrap <symbol>) yang memungkinkan Anda menulis pembungkus tanpa harus menggunakan tautan ganda:

/* yourlib.c */
#include <stdio.h>

int __real_open(const char *pathname, int flags)

int __wrap_open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    /* the undefined reference here will resolve to "open" at linking time */
    return __real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1; 
  }
}
sleblanc
sumber
2

Pindahkan file konfigurasi Anda, dan tulis pembungkus skrip shell untuk kasus penggunaan interaktif yang menyalin file ke tujuan normalnya, menjalankan program, dan menghapusnya saat keluar.

Tink
sumber
Lihat hasil edit saya baru-baru ini: Saya tidak mengontrol penjadwalan batch, jadi saya mungkin menggunakan program secara interaktif dan sebagai bagian dari pekerjaan batch pada saat yang sama.
Jeffrey Bosboom
1

Ini harus dimungkinkan dengan unionfs / aufs. Anda menciptakan chrootlingkungan untuk proses tersebut. Anda menggunakan direktori nyata sebagai lapisan read-only dan meletakkan yang kosong di atasnya. Kemudian Anda memasang volume unionfs ke direktori masing-masing di chrootlingkungan dan menghapus file di sana. Proses tidak akan melihatnya tetapi semua orang lain melakukannya.

Hauke ​​Laging
sumber
0

Ubah nama file config menjadi eg config.interactive. Buat file kosong lain bernama eg config.script.

Sekarang, buat tautan lunak yang disebut config(atau apa pun yang diharapkan aplikasi sebagai file konfigurasi) ke konfigurasi mana pun yang Anda perlukan dan jalankan aplikasi Anda.

ln -s config.interactive config

Ingatlah untuk merapikan tautan Anda sesudahnya.

garethTheRed
sumber
Lihat hasil edit saya baru-baru ini: Saya tidak mengontrol penjadwalan batch, jadi saya mungkin menggunakan program secara interaktif dan sebagai bagian dari pekerjaan batch pada saat yang sama. Jawaban ini pada dasarnya sama dengan memindahkan file, baik secara manual atau dengan skrip.
Jeffrey Bosboom
1
Doh! Saya perlu berpikir dan mengetik lebih cepat. Apakah ini aplikasi besar? Bisakah itu ditransfer ke chroot dan dijalankan dari sana secara interaktif? Itu semua tergantung pada apa yang berinteraksi dengan program, saya kira. Ini juga bisa menjadi tugas yang sangat membosankan untuk mendapatkan semua yang dibutuhkan menjadi chroot juga. (Saya pikir saya sudah berbicara sendiri tentang opsi itu!)
garethTheRed
0

Jika Anda benar-benar menandai bagaimana program Anda menggunakan file konfigurasi, saya telah mengabaikannya. Banyak program (seperti bashdan vi) akan memeriksa file konfigurasi segera setelah mulai; jika file ada, baca dan tutup. Program-program ini tidak pernah mengakses file inisialisasi ini lagi. Jika program Anda seperti itu, baca terus.

Saya tahu Anda telah menolak jawaban yang membuat file konfigurasi benar-benar tidak ada (dengan menamai ulangnya), tetapi saya memiliki kerutan yang belum pernah saya lihat diusulkan oleh orang lain. Lakukan ini ketika Anda menjalankan program dalam mode batch:

DELAY_TIME=1
REALPATH="~/.config/myprogram"
HOLDPATH="${REALPATH}.hold"

mv "$REALPATH" "$HOLDPATH"
(sleep "$DELAY_TIME"; mv "$HOLDPATH" "$REALPATH")&
myprogram

Ini memindahkan file konfigurasi keluar dari jalan, tetapi kemudian memindahkannya kembali satu detik kemudian, bahkan jika myprogrammasih berjalan. Ini menciptakan jendela waktu yang sangat singkat di mana file tidak tersedia - berapakah probabilitas Anda akan menjalankan program secara interaktif selama jendela ini? (Bahkan jika Anda melakukannya, Anda dapat keluar dan memulai kembali, dan file konfigurasi mungkin akan kembali pada tempatnya.)

Ini memang menciptakan kondisi balapan; jika program membutuhkan waktu terlalu lama untuk membuka file, itu mungkin mendapatkan file yang sebenarnya. Jika ini terjadi cukup sering sehingga menjadi masalah, cukup tambahkan nilai DELAY_TIME.

Scott
sumber
1
Apa hal terburuk yang bisa salah? Saya benar-benar melihat itu terjadi. Dalam produksi.
Henk Langeveld
-1

Saya suka jawaban Stephane, tetapi ini akan menipu program mana pun untuk meyakini bahwa file apa pun kosong - (karena dentry-nya sementara menunjuk ke file yang benar-benar kosong) :

cat <./test.txt
###OUTPUT###
notempty

mount --bind /dev/null ./test.txt
cat <./test.txt
###NO OUTPUT###

umount ./test.txt
cat <./test.txt
###OUTPUT###
notempty

Anda juga bisa:

mount --bind ./someotherconfig.conf ./unwanted.conf

Jika kamu mau.

mikeserv
sumber
Ini pada dasarnya setara dengan beberapa jawaban sebelumnya (kecuali, saya percaya, yang satu ini mengharuskan pengguna diistimewakan). OP menolak jawaban-jawaban lain itu karena ia tidak ingin mengelabui proses apa pun - ia ingin mengelabui permintaan batch program, sementara membiarkan doa interaktif melihat file konfigurasi secara normal.
Scott
@Scott - saya tidak setuju - setiap jawaban lain sebelum ini merekomendasikan beberapa variasi pada mvfile - yang mungkin memiliki konsekuensi lain selain mempengaruhi dentry-nya seperti benar-benar memotong file atau yang lainnya dan lain-lain - padahal ini hanya beroperasi pada apa-apa selain. Namun, saya harus unshareitu mountsaya kira ...
mikeserv