
我有一個程式儲存其設置,~/.config/myprogram
我可以互動式地使用該程式並與批次排隊系統一起使用。當交互運行時,我希望這個程式使用我的設定檔(它確實如此)。但在批次模式下運行時,不需要配置文件,因為我指定了覆蓋所有相關設定的命令列選項。此外,透過網路存取設定檔會使程式的啟動時間增加幾秒鐘;如果檔案不存在,程式啟動速度會更快(因為每個作業只需要大約一分鐘,這對批次作業吞吐量有重大影響)。但因為我也以互動方式使用該程序,所以我不想一直移動/刪除我的設定檔。根據我的批次作業在叢集上安排的時間(基於其他使用者的使用情況),我可能希望以互動方式使用該程序,同時作為批次作業的一部分。
(旁白:網路檔案效能如此緩慢可能是個錯誤,但我只是叢集的用戶,所以我只能解決它,而不能修復它。)
我可以建立一個不讀取設定檔(或具有不讀取設定檔的命令列選項)的程式版本以供批次使用,但該程式的建置環境設計不佳且難以設定。我更喜歡使用透過系統的套件管理器安裝的二進位檔案。
如何欺騙該程式的特定實例假裝我的設定檔不存在(無需修改程式)?我希望有一個 form 的包裝器 pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options...
,但我對其他解決方案持開放態度。
答案1
該程式可能會解析從 到該檔案的路徑$HOME/.config/myprogram
。所以你可以告訴它你的主目錄在其他地方,例如:
HOME=/nowhere your-program
現在,也許您的程式需要主目錄中的一些其他資源。如果您知道它們是什麼,您可以為您的程式準備一個假主頁,其中包含指向該程式所需資源的連結。
mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram
答案2
如果所有其他方法都失敗,請編寫您將注入的包裝器庫,LD_PRELOAD
以便攔截調用open("/home/you/my-program/config.interactive")
,但任何其他調用都會通過。這適用於任何類型的程序,甚至是 shell 腳本,因為它會過濾系統呼叫。
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;
}
}
注意:我尚未測試此程式碼,而且我不能 100% 確定該errno
部分是否有效。
看看怎麼樣fakeroot
getuid(2)
對於和等調用執行此操作stat(2)
。
基本上,連結器會將該應用程式連結到您的庫,從而覆寫該open
符號。由於您不能使用您自己的庫中命名的兩個不同的函數open
,因此您必須將其分隔在第二部分(例如get_real_open
)中,該部分將依次連結到原始open
呼叫。
原來的:./Application
Application -----> libc.so
open()
攔截:LD_PRELOAD=yourlib_wrap.so ./Application
Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
open() get_real_open() open()
編輯:顯然您可以啟用一個ld
標誌 ( --wrap <symbol>
),它允許您編寫包裝器而不必求助於雙重連結:
/* 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;
}
}
答案3
將設定檔移開,並為互動式用例編寫一個 shell 腳本包裝器,將檔案複製到其正常目標,運行程序,並在退出時將其刪除。
答案4
將設定檔重命名為例如config.interactive
.建立另一個名為 例如 的空檔案config.script
。
config
現在,建立一個名為(或應用程式期望的設定檔的任何內容)的軟連結到您需要的任何實際配置並運行您的應用程式。
ln -s config.interactive config
請記住事後整理您的連結。