Bir dosyanın var olmadığını düşünerek bir süreci nasıl kandırabilirim?


31

Ayarlarını saklayan bir programım var. ~/.config/myprogramhem etkileşimli olarak hem de toplu kuyruklama sistemiyle kullanıyorum. Etkileşimli olarak çalıştırırken, bu programın yapılandırma dosyalarımı kullanmasını istiyorum (ve kullanıyor). Ancak toplu modda çalışırken, tüm ilgili ayarların üzerine yazacak komut satırı seçeneklerini belirttiğim için yapılandırma dosyaları gerekli değildir. Ayrıca, ağ üzerinden yapılandırma dosyalarına erişmek, programın başlangıç ​​süresini birkaç saniye artırır; dosyalar yoksa, program çok daha hızlı başlar (her iş yalnızca bir dakika sürdüğü için, bunun toplu iş çıktısı üzerinde önemli bir etkisi vardır). Ancak programı etkileşimli olarak da kullandığım için, yapılandırma dosyalarımı her zaman taşımak / silmek istemiyorum. Toplu işlerimin kümede ne zaman planlanacağına bağlı olarak (diğer kullanıcıların kullanımına bağlı olarak),

(Bir kenara: bu ağ dosyası performansı çok yavaş bir hata olabilir, ama ben sadece küme kullanıcısıyım, bu yüzden sadece üzerinde çalışabilirim, düzeltemem.)

Toplu kullanım için yapılandırma dosyalarını okumayan (veya bir komut satırı seçeneğine sahip olmayan) programın bir sürümünü oluşturabilirim, ancak bu programın oluşturma ortamı kötü tasarlanmış ve ayarlanması zor. Sistemimin paket yöneticisi aracılığıyla yüklenen ikilileri kullanmayı tercih ederim.

Bu programın belirli örneklerini yapılandırma dosyalarımı yokmuş gibi (programda değişiklik yapmadan) nasıl kandırabilirim? Formun bir paketleyicisini umuyorum pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options..., ancak diğer çözümlere açığım.


2
Dosyayı okuma iznine sahip olmayan bir kullanıcı olarak çalıştırabilirsiniz.
psimon

1
@psimon Kümenin "sadece bir kullanıcısı" olarak toplu işimi çalıştırmak için yeni bir kullanıcı oluşturamıyorum. Bu akıllıca bir fikir olsa da, daha iyi bir önerim yoksa küme yöneticisini benim için yapması için hata yapacağım.
Jeffrey Bosboom

Veya önce config dosyasını yeniden adlandıran, programı çalıştıran ve sonra config dosyasını yeniden adlandıran bir komut dosyası kurun.
psimon

@ psimon Daha net olabileceğimi düşünüyorum: Toplu işlerimin kümede ne zaman planlandığına bağlı olarak, programı etkileşimli olarak ve toplu halde aynı anda kullanıyor olabilirim.
Jeffrey Bosboom

1
Evet, dinamik olarak bağlıysa, bir LD_PRELOADkanca kullanabilirsiniz . Bu daha kolay (C'yi biliyorsanız, bir veya iki saat içinde uygulayabilirsiniz) alternatif olandan ptrace. Ayrıca muhtemelen bunu yapmak için fakechroot kullanabilirsiniz (LD_PRELOAD, sanırım).
derobert

Yanıtlar:


33

Bu program muhtemelen o dosyanın yolunu çözer $HOME/.config/myprogram. Böylece ev dizininizin başka bir yerde olduğunu söyleyebilirsiniz:

HOME=/nowhere your-program

Şimdi, belki de programınızın ana dizininizdeki başka bir kaynağa ihtiyacı var. Bunların hangileri olduğunu biliyorsanız, programınız için ihtiyaç duyduğu kaynağa bağlantılar içeren sahte bir ev hazırlayabilirsiniz.

mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram

5
Bu cevap benim sorunumu çözdü, bu yüzden bu sorunun başlığındaki soruya genel bir cevap olmasa da kabul ettim. Başka bir cevapta tarif edildiği gibi bir ön yükleme kancası, daha genel (aynı zamanda daha yüksek eforlu) bir çözümdür.
Jeffrey Bosboom

28

Diğer her şey başarısız olursa, LD_PRELOADaramaya open("/home/you/my-program/config.interactive")müdahale edilmek üzere başkalarına geçecek şekilde enjekte edeceğiniz bir sarmalayıcı kitaplığı yazın . Bu, sistem çağrılarını filtreleyeceği için, herhangi bir program türü için, hatta kabuk komut dosyaları için de geçerlidir.

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;
  }
}

Not: Bu kodu test etmedim ve errnoparçanın çalıştığından % 100 emin değilim .

Ve fakerootgibi çağrılar için nasıl yapıldığına bakın .getuid(2)stat(2)

Temel olarak, bağlayıcı bu uygulamayı opensembolünüze geçersiz kılan kütüphanenize bağlar . openKendi kütüphanenizde isimlendirilen iki farklı işlevi kullanamadığınızdan , onu get_real_openorijinal openaramaya bağlayacak ikinci bir bölüme (örneğin ) ayırmanız gerekir .

Orijinal: ./Application

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

Intercepted: LD_PRELOAD=yourlib_wrap.so ./Application

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

Düzenleme: Görünüşe göreld etkinleştirebileceğiniz bir bayrak ( --wrap <symbol>), çift bağlantıya başvurmak zorunda kalmadan sarmalayıcılar yazmanıza olanak sağlayan:

/* 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; 
  }
}

2

Config dosyanızı yolun dışına taşıyın ve dosyayı normal hedefine kopyalayan, programı çalıştıran ve çıkışta silen etkileşimli kullanım için bir kabuk komut dosyası sargısı yazın.


En son düzenlememe bakın: Parti zamanlamasını kontrol etmiyorum, bu nedenle programı etkileşimli olarak ve aynı anda bir toplu işin parçası olarak kullanıyor olabilirim.
Jeffrey Bosboom

1

Bu unionfs / aufs ile mümkün olmalıdır. chrootİşlem için bir ortam yaratıyorsunuz . Real dizinini salt okunur katman olarak kullanır ve üstüne boş bir tane koyarsınız. Daha sonra unionfs birimini chrootortamdaki ilgili dizine bağlar ve oradaki dosyayı siler. Süreç bunu görmeyecek ama diğerleri de görecek.


0

Örneğin config dosyasını yeniden adlandırın config.interactive. Örneğin, başka bir boş dosya oluşturun config.script.

Şimdi, configihtiyacınız olan gerçek yapılandırmaya ihtiyaç duyduğunuz ve uygulamanızı çalıştıran denilen yumuşak bir bağlantı oluşturun (veya uygulamanın bir yapılandırma dosyası olarak beklediği her neyse).

ln -s config.interactive config

Daha sonra bağlantınızı düzeltmeyi unutmayın.


En son düzenlememe bakın: Parti zamanlamasını kontrol etmiyorum, bu nedenle programı etkileşimli olarak ve aynı anda bir toplu işin parçası olarak kullanıyor olabilirim. Bu cevap aslında dosyaları elle veya bir komut dosyasıyla dolaştırmakla aynıdır.
Jeffrey Bosboom

1
Doh! Daha hızlı düşünmem ve yazmam gerekiyor. Büyük bir uygulama mı? Bir chroot'a aktarılıp etkileşimli olarak oradan kaçabilir mi? Her şey programın neyle etkileşime girdiğine bağlı, sanırım. İhtiyacı olan her şeyi chroot yapmak için de çok sıkıcı bir görev olabilir. (Sanırım bu seçeneğin dışında kendimle konuştum!)
garethTheRed

0

Programınızın yapılandırma dosyasını nasıl kullandığını tam olarak nitelendirdiyseniz , gözardı ettim. Birçok program ( bashve gibi vi) başlangıçta hemen bir yapılandırma dosyasını kontrol edecektir; Dosya varsa, onu okuyun ve kapatın. Bu programlar bir daha asla bu başlatma dosyalarına erişmez. Programınız böyle ise, okumaya devam edin.

Yapılandırma dosyasını gerçekten varolmayan kılan yanıtları reddettiğinizi biliyorum (yeniden adlandırarak), ancak başkası tarafından önerilen bir kırışıklık yaşamadım. Programı toplu modunda başlattığınızda bunu yapın:

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

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

Bu, yapılandırma dosyasını yoldan çıkarır, ancak daha sonra myprogramçalışıyor olsa bile bir saniye sonra geri taşır . Bu, dosyanın kullanılamadığı çok kısa bir zaman penceresi yaratır - programı bu pencerede etkileşimli olarak çalıştırma olasılığı nedir? (Yapsanız bile, sadece çıkıp yeniden başlatabilirsiniz ve config dosyası muhtemelen tekrar devreye girecektir.)

Bu bir yarış durumu yaratır; Program dosyayı açmak için etrafta dolaşmak için çok uzun sürerse, gerçek dosyayı alabilir. Bu bir problem olması için yeterince sık görülürse, sadece DELAY_TIME değerini arttırın.


1
Yanlış gidebilecek en kötü şey nedir? Kelimenin tam anlamıyla bunun olduğunu gördüm. Üretimde.
Henk Langeveld

-1

Stephane'ın cevap gibi ben, ama bu olacak kandırmak herhangi bir dosyayı inanan içine herhangi bir program olan boş - (kendi dentry geçici aslında boş olduğunu bir dosyaya işaret ettiğinden) :

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

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

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

Ayrıca yapabilirdin:

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

Eğer istersen.


Bu aslında önceki cevapların birkaçına eşdeğerdir (bunun dışında kullanıcının ayrıcalıklı olmasını gerektirdiğine inanıyorum). OP bu diğer cevapları reddetti çünkü herhangi bir süreci kandırmak istemedi - etkileşimli çağrının config dosyasını normal olarak görmesine izin verirken, programın toplu çağrılarını kandırmak istiyor.
Scott

@Scott - katılmıyorum - bundan önceki tüm cevaplar mvdosyada bazı değişiklikler önerdi - ki bu da aslında dosyaya veya başkalarına kısaltmak gibi takma dişlerini etkilemekten başka sonuçları olabilir - bunun dışında hiçbir şey yapmıyor. Yine de tahmin etmeliyim unshareki mount...
mikeserv
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.