让Linux软件在单独的Home文件夹下运行
开局一张图,是不是立马就开始难受起来了
为了尽量避免此类情况,我用了我生命中好多好多秒,写了一个python脚本,用于在运行前自动设置一个用户自己定义的文件夹作为主目录,可以做到每个软件都具有自己的主目录。
介绍
先介绍一下这个脚本:
用法: ./runapp.py 可执行文件路径 虚拟的home目录(必须存在) [可执行程序的参数列表]
介绍:本程序用于将可执行文件通过修改环境变量的方式将其配置文件和Home目录限制在一个固定的文件夹下,以达到纯净的目的。每次运行之前,本程序会自动将真正的主目录下的所有非隐藏的文件以及文件夹软链接至虚拟主目录,以方便访问。但是隐藏目录将被忽略。
这将导致一些问题,请不要对包含此类功能的程序应用本程序:
1.需要操作配置文件(因为软件拥有自己的主目录,所以对于主目录下配置的一切修改都无法于用户环境生效)
2.需要输出文件到主目录的根目录下(因为我们会将真正的主目录下内容软链接到虚拟主目录,但是我们并不反向操作,因此程序若在主目录下保存文件,您将无法直接在您的主目录下找到它)
3.需要读取主目录下的资源数据文件(一般情况数据文件都存在隐藏文件夹中,如一些游戏,当你手动部署资源文件到隐藏文件夹后,程序将不能正确读取,但是你可以手动部署至隐藏主目录)
上边这段文字会在脚本后不追加参数时显示。
举个例子
其中motrix_home
文件夹必须存在,如果需要为软件追加参数的话,可以直接在第三个参数的位置追加。
运行此命令后,Motrix将以motrix_home这个文件夹作为用户主目录,其生成的配置文件等也都会存在对应的目录下,实现了与真正的主目录隔离的效果。
目录内容:
由于软件很有可能有访问用户的各个文件夹的需要,所以,脚本中将自动把用户主目录里的所有未隐藏的内容软链接到这个虚拟的主目录下,这样就方便了软件的访问。
同时,每次使用这个脚本时,脚本会自动检测新的没有被链接的文件或文件夹进行链接,也会自动删除过期的链接。
下面是脚本的所有内容:
#!/bin/python3
#coding=utf-8
# 作者:Maicss
# 邮箱:maicss@126.com
# 更新时间:2021年5月22日
# 参数:可执行文件路径,虚拟的home目录(必须存在),[可执行程序的参数列表]
# 备注:本程序用于将可执行文件通过修改环境变量的方式将其配置文件和Home目
# 录限制在一个固定的文件夹下,以达到纯净的目的。
# 缺点:可能无法及时更新软链接
import os
import sys
argv = sys.argv
if len(argv)<3 :
print("用法: "+argv[0]+" 可执行文件路径 虚拟的home目录(必须存在) [可执行程序的参数列表]")
print("介绍:本程序用于将可执行文件通过修改环境变量的方式将其配置文件和Home目录限制在一个固定的文件夹下,以达到纯净的目的。")
print("每次运行之前,本程序会自动将真正的主目录下的所有非隐藏的文件以及文件夹软链接至虚拟主目录,以方便访问。但是隐藏目录将被忽略。")
print("这将导致一些问题,请不要对包含此类功能的程序应用本程序:")
print("\t1.需要操作配置文件(因为软件拥有自己的主目录,所以对于主目录下配置的一切修改都无法于用户环境生效)")
print("\t2.需要输出文件到主目录的根目录下(因为我们会将真正的主目录下内容软链接到虚拟主目录,但是我们并不反向操作,因此程序若在主目录下保存文件,您将无法直接在您的主目录下找到它)")
print("\t3.需要读取主目录下的资源数据文件(一般情况数据文件都存在隐藏文件夹中,如一些游戏,当你手动部署资源文件到隐藏文件夹后,程序将不能正确读取,但是你可以手动部署至隐藏主目录)")
sys.exit(-1)
nowHome = os.getenv("HOME")
appPath = argv[1]
newHome = argv[2]
appArgv = argv[3:]
print("当前Home目录:",nowHome)
print("虚拟的Home目录:",newHome)
print("App的参数:",appArgv)
if not os.path.isdir(newHome):
print ("您选中的虚拟主目录不存在")
sys.exit(-1)
if not os.path.isfile(appPath):
print ("没有找到",appPath)
sys.exit(-1)
print("开始设置环境变量...")
env=os.environ
env["HOME"]=newHome
if os.getenv("HOME")==newHome:
print("HOME...OK")
else:
print("HOME...失败")
exit(-1)
cachePath=newHome+"/.cache"
cachePath = cachePath.replace("//","/")
if not os.path.exists(cachePath):
os.mkdir(cachePath)
env["XDG_CACHE_HOME"]=cachePath
if os.getenv("XDG_CACHE_HOME")==cachePath and os.path.isdir(cachePath):
print("XDG_CACHE_HOME...OK")
else:
print("XDG_CACHE_HOME...失败")
exit(-1)
configPath=newHome+"/.config"
configPath = configPath.replace("//","/")
if not os.path.exists(configPath):
os.mkdir(configPath)
env["XDG_CONFIG_HOME"]=configPath
if os.getenv("XDG_CONFIG_HOME")==configPath and os.path.isdir(configPath):
print("XDG_CONFIG_HOME...OK")
else:
print("XDG_CONFIG_HOME...失败")
exit(-1)
dataPath=newHome+"/.local/share"
dataPath=dataPath.replace("//","/")
if not os.path.exists(dataPath):
os.makedirs(dataPath)
env["XDG_DATA_HOME"]=dataPath
if os.getenv("XDG_DATA_HOME")==dataPath and os.path.isdir(dataPath):
print("XDG_DATA_HOME...OK")
else:
print("XDG_DATA_HOME...失败")
exit(-1)
print("更新常用目录软链接...")
donotln = [".config",".local",".cache"]
inHome = os.listdir(nowHome)
inNewHome = os.listdir(newHome)
for dir in inNewHome:
if os.path.islink(newHome+"/"+dir):
if not os.path.exists(os.readlink(newHome+"/"+dir)):
os.remove(newHome+"/"+dir)
for dir in inHome:
if dir not in donotln and dir[:1]!="." and not os.path.exists(newHome+"/"+dir):
print("link:"+dir)
os.symlink(nowHome+"/"+dir,newHome+"/"+dir)
str_argv=""
for arg in appArgv:
str_argv+=" "+arg
exitCode = os.system(appPath+str_argv)
print("程序运行结束:",exitCode)
exit(exitCode)