380 lines
13 KiB
C++
380 lines
13 KiB
C++
|
||
/**********************************************************************************
|
||
* @file SetupFuncLinux.cpp
|
||
* @brief Linux系统设置函数
|
||
* @author yikenan
|
||
* @versiong 1.0
|
||
* @date
|
||
**********************************************************************************/
|
||
|
||
//< 仅在Linux系统下编译
|
||
#ifdef OS_LINUX
|
||
|
||
#include <QtCore>
|
||
#include "SetupFunc.h"
|
||
#include "setupCommon.h"
|
||
#include <QStandardPaths>
|
||
#include <QProcess>
|
||
#include "setup/CommonDef.h"
|
||
|
||
namespace iot_sys
|
||
{
|
||
|
||
QString getDesktopPath()
|
||
{
|
||
QString username = qgetenv("SUDO_USER");
|
||
QProcess process;
|
||
QString cmd = QString("su %1 -c \"xdg-user-dir DESKTOP\"").arg(username);
|
||
process.start(cmd);
|
||
process.waitForFinished(-1); // will wait forever until finished
|
||
|
||
QString stdout = process.readAllStandardOutput().trimmed();
|
||
if( strcmp(g_iscs6000_os,"oe2203_aarch64") == 0 && stdout.isEmpty() )
|
||
{
|
||
return QString("/home/%1/Desktop").arg(username);
|
||
}
|
||
else
|
||
{
|
||
return stdout;
|
||
}
|
||
}
|
||
|
||
const QString desktopDir = getDesktopPath();
|
||
|
||
|
||
//< 注册系统服务,并设置自启动
|
||
bool regSysService(QString &strErr,QString path)
|
||
{
|
||
//< 判断服务是否已注册,普通用户权限可执行
|
||
if (0 == QProcess::execute(QString("systemctl is-enabled %1.service").arg(g_pszLauncherServiceName) ) )
|
||
{
|
||
strErr = QObject::tr("已设置服务自启动,若需重新设置,请先取消!");
|
||
return false;
|
||
}
|
||
|
||
const QString strExec = path + "/platform/" + g_platform_dir_name + "/sys_launcher_srv";
|
||
|
||
//< 判断文件存在并设置可执行权限
|
||
if (QFile::exists(strExec))
|
||
{
|
||
if(QFileDevice::ExeOther !=
|
||
(QFileDevice::ExeOther & QFile::permissions(strExec)))
|
||
{
|
||
QString strCmd = "chmod +x ";
|
||
strCmd += strExec;
|
||
if(0 != QProcess::execute(strCmd))
|
||
{
|
||
strErr = QObject::tr("设置可执行权限失败!") + "\n" + strExec;
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
strErr = QObject::tr("文件不存在!")+ "\n" + strExec;
|
||
return false;
|
||
}
|
||
|
||
//< 生成或修改systemd服务配置文件
|
||
{
|
||
QSettings objIniSetting(g_pszLauncherServiceFile, QSettings::IniFormat);
|
||
objIniSetting.setIniCodec( QTextCodec::codecForLocale() );
|
||
|
||
if (!objIniSetting.isWritable())
|
||
{
|
||
strErr = QObject::tr("服务配置文件不可写,请确认是否具有权限!")
|
||
+ "\n" + g_pszLauncherServiceFile;
|
||
return false;
|
||
}
|
||
|
||
//< 清空所有原有配置
|
||
objIniSetting.setFallbacksEnabled(false);
|
||
objIniSetting.clear();
|
||
|
||
objIniSetting.beginGroup("Unit");
|
||
objIniSetting.setValue("Description", g_pszLauncherServiceName);
|
||
objIniSetting.setValue("After", "network.target");
|
||
objIniSetting.endGroup();
|
||
|
||
objIniSetting.beginGroup("Service");
|
||
objIniSetting.setValue("Type", "simple");
|
||
objIniSetting.setValue("ExecStart", strExec);
|
||
objIniSetting.setValue("KillMode", "process");
|
||
objIniSetting.setValue("Restart", "on-failure");
|
||
objIniSetting.setValue("RestartSec", "42s");
|
||
QString username = qgetenv("SUDO_USER");
|
||
if( !username.isEmpty() )
|
||
{
|
||
objIniSetting.setValue("User",username);
|
||
}
|
||
|
||
objIniSetting.endGroup();
|
||
|
||
objIniSetting.beginGroup("Install");
|
||
objIniSetting.setValue("WantedBy", "multi-user.target");
|
||
objIniSetting.endGroup();
|
||
|
||
if (QSettings::NoError != objIniSetting.status())
|
||
{
|
||
strErr = QObject::tr("写入服务配置文件失败!")
|
||
+ "\n" + g_pszLauncherServiceFile;
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//< systemd重新加载配置文件
|
||
if (0 != QProcess::execute("systemctl daemon-reload"))
|
||
{
|
||
strErr = QObject::tr("调用系统重新加载配置失败!");
|
||
return false;
|
||
}
|
||
|
||
//< 设置服务开机自启动
|
||
if (0 != QProcess::execute(QString("systemctl enable %1.service").arg(g_pszLauncherServiceName) ))
|
||
{
|
||
strErr = QObject::tr("设置服务开机自启动失败!");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
//----------------------------------------
|
||
|
||
//< 设置HMI自启动
|
||
bool setHmiAutoStart(QString &strErr,QString path)
|
||
{
|
||
QString sudo_user = qgetenv("SUDO_USER");
|
||
QString user = qgetenv("USER");
|
||
|
||
QString strCfgFileDir;
|
||
if(user == "root" && sudo_user.isEmpty())
|
||
{
|
||
strCfgFileDir = "/root";
|
||
sudo_user = "root";
|
||
}
|
||
else
|
||
{
|
||
strCfgFileDir = QString("/home/%1").arg(sudo_user);
|
||
}
|
||
strCfgFileDir += g_pszXdgAutoStartCfgDir;
|
||
|
||
const QString strCfgFileFullPath = strCfgFileDir + g_pszHMIXdgDesktopCfgFile;
|
||
|
||
if (QFile::exists(strCfgFileFullPath))
|
||
{
|
||
strErr = QObject::tr("已设置HMI自启动,若需重新设置,请先取消!");
|
||
return false;
|
||
}
|
||
|
||
const QString strExec = path + "/product/" + g_platform_dir_name + "/sys_startup";
|
||
|
||
//< 判断文件存在并设置可执行权限
|
||
if (QFile::exists(strExec))
|
||
{
|
||
if(QFileDevice::ExeOther !=
|
||
(QFileDevice::ExeOther & QFile::permissions(strExec)))
|
||
{
|
||
QString strCmd = "chmod +x ";
|
||
strCmd += strExec;
|
||
if(0 != QProcess::execute(strCmd))
|
||
{
|
||
strErr = QObject::tr("设置可执行权限失败!")
|
||
+ "\n" + strExec;
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
strErr = QObject::tr("文件不存在!") + "\n" + strExec;
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
启动器中的Group “Desktop Entry”,中间带有空格
|
||
而QSettings对于Group、Key都是强制转URL的,于是空格变成 %20
|
||
可是这样的写法,xdg不认
|
||
所以,不使用QSettings
|
||
*/
|
||
|
||
//< 生成或复写启动器文件
|
||
{
|
||
//< 防止路径不存在,先建立
|
||
QDir objDir(strCfgFileDir);
|
||
if(!objDir.exists())
|
||
{
|
||
objDir.mkpath(strCfgFileDir);
|
||
}
|
||
|
||
QFile objFile(strCfgFileFullPath);
|
||
if (!objFile.open(QIODevice::WriteOnly | QIODevice::Text))
|
||
{
|
||
strErr = QObject::tr("启动器文件不可写,请确认是否具有权限!")
|
||
+ "\n" + strCfgFileFullPath;
|
||
return false;
|
||
}
|
||
|
||
{
|
||
QTextStream objStreamOut(&objFile);
|
||
objStreamOut << "[Desktop Entry]" << endl;
|
||
objStreamOut << "Name=" << g_pszHMIXdgDesktopName << endl;
|
||
objStreamOut << "Exec=" << strExec << endl;
|
||
objStreamOut << "Type=Application" << endl;
|
||
objStreamOut << "X-GNOME-AutoRestart=false" << endl;
|
||
}
|
||
|
||
objFile.close();
|
||
}
|
||
QString stFilePerm = QString("chown -R %1:%1 %2").arg(sudo_user).arg(strCfgFileDir);
|
||
system(stFilePerm.toStdString().c_str());
|
||
return true;
|
||
}
|
||
|
||
|
||
//----------------------------------------
|
||
class CDesktopEntry
|
||
{
|
||
public:
|
||
QString desktopName;
|
||
QString name;
|
||
QString comment;
|
||
QString exec;
|
||
QString icon;
|
||
|
||
// 用于窗体识别,解决某些桌面组件无法识别窗体而导致的问题
|
||
// 比如dash-to-dock上收藏的图标与运行的图标分离(正常应该是一个图标)
|
||
// 参见:https://github.com/micheleg/dash-to-dock/issues/215
|
||
QString startupWMClass;
|
||
|
||
CDesktopEntry(const QString destopName_,const QString name_, const QString comment_, const QString exec_,
|
||
const QString icon_="", const QString startupWMClass_=""):
|
||
desktopName(destopName_),
|
||
name(name_),
|
||
comment(comment_),
|
||
exec(exec_),
|
||
icon(icon_),
|
||
startupWMClass(startupWMClass_)
|
||
{
|
||
}
|
||
|
||
};
|
||
|
||
|
||
bool createDesktopEntry(const QString &entrypath, const CDesktopEntry &entry, QString &strErr,bool isRoot = true)
|
||
{
|
||
|
||
const QString entryFileFullPath = entrypath + "/" + entry.desktopName + ".desktop";
|
||
|
||
//< 生成desktop文件
|
||
{
|
||
QFile objFile(entryFileFullPath);
|
||
if (!objFile.open(QIODevice::WriteOnly | QIODevice::Text))
|
||
{
|
||
strErr = QObject::tr("快捷方式不可写,请确认是否具有权限!")
|
||
+ "\n" + entryFileFullPath;
|
||
return false;
|
||
}
|
||
{
|
||
QTextStream objStreamOut(&objFile);
|
||
objStreamOut << "[Desktop Entry]" << endl;
|
||
objStreamOut << "Name=" << entry.name << endl;
|
||
objStreamOut << "Exec=" << entry.exec <<endl;
|
||
objStreamOut << "Comment=" << entry.comment << endl;
|
||
if(!entry.icon.isEmpty())
|
||
objStreamOut << "Icon=" << entry.icon << endl;
|
||
if(!entry.startupWMClass.isEmpty())
|
||
objStreamOut << "StartupWMClass=" << entry.startupWMClass << endl;
|
||
objStreamOut << "Type=Application" << endl;
|
||
objStreamOut << "Categories=GNOME;Application;Other;Settings" << endl;
|
||
}
|
||
|
||
objFile.close();
|
||
}
|
||
QString chmodStr = QString("chmod +x ") + entryFileFullPath;
|
||
system(chmodStr.toStdString().c_str());
|
||
if(!isRoot)
|
||
{
|
||
QString username = qgetenv("SUDO_USER");
|
||
QString chownStr = QString("chown %1 ").arg(username) + entryFileFullPath;
|
||
system(chownStr.toStdString().c_str());
|
||
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
|
||
//< 创建快捷方式
|
||
bool creatShortcut(QString &strErr,QString path)
|
||
{
|
||
//<todo yikenan 路径需改动
|
||
const QString execProdDir = path + "/product/" + g_platform_dir_name;
|
||
const QString execPlatDir = path + "/platform/" + g_platform_dir_name;
|
||
|
||
|
||
const QString iconDir = path + "/resource/zh/setup/icons";
|
||
QDir appDir(g_pszAppDir);
|
||
appDir.mkdir(g_pszDesktopEntryDirName);
|
||
QString appDestPath = appDir.absoluteFilePath(g_pszDesktopEntryDirName);
|
||
if(!QDir(appDestPath).exists())
|
||
{
|
||
strErr = appDestPath + QObject::tr("不存在或无法创建");
|
||
return false;
|
||
}
|
||
|
||
createDesktopEntry(desktopDir,CDesktopEntry("sys_startup",QObject::tr("实时监控"),"system management",execProdDir+"/sys_startup",iconDir + "/sys_startup.ico", "sys_startup"),strErr,false);
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
bool createStartProgram(QString &strErr,const QString& path)
|
||
{
|
||
//<todo yikenan 路径需改动
|
||
const QString execProdDir = path + "/product/" + g_platform_dir_name;
|
||
const QString execPlatDir = path + "/platform/" + g_platform_dir_name;
|
||
|
||
|
||
const QString iconDir = path + "/resource/zh/setup/icons";
|
||
QDir appDir(g_pszAppDir);
|
||
appDir.mkdir(g_pszDesktopEntryDirName);
|
||
QString appDestPath = appDir.absoluteFilePath(g_pszDesktopEntryDirName);
|
||
if(!QDir(appDestPath).exists())
|
||
{
|
||
strErr = appDestPath + QObject::tr("不存在或无法创建");
|
||
return false;
|
||
}
|
||
|
||
createDesktopEntry(appDestPath,CDesktopEntry("sys_dog_auth_check", QObject::tr("超级狗检查"), "check system dog authentication",execProdDir+"/sys_dog_auth_check"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("FesSim", QObject::tr("前置调试"),"fes debug tool",execProdDir+"/FesSim",iconDir + "/fes_sim.ico"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("debug_tool", QObject::tr("工程调试工具"),"debug tool",execProdDir+"/debug_tool",iconDir + "/debug_tool.ico"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("sys_command",QObject::tr("命令窗口"),"bin exec environment",execProdDir+"/sys_command.sh"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("model_system_config",QObject::tr("系统建模"),"system model configuration",execPlatDir+"/model_system_config",iconDir + "/systemConfig.ico"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("model_studio",QObject::tr("设备建模"),"model studio",execPlatDir+"/model_studio",iconDir + "/studio.ico"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("hmi",QObject::tr("画面组态"),"human machine interface app",execPlatDir+"/hmi",iconDir + "/fes_sim.ico"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("fbd_editor",QObject::tr("逻辑编程"),"fbd editor",execPlatDir+"/fbd_designer",iconDir + "/fbd_editor.ico"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("db_manager",QObject::tr("工程管理"),"database management",execPlatDir+"/db_manager",iconDir + "/db_manager.ico"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("sys_startup",QObject::tr("实时监控"),"system management",execProdDir+"/sys_startup",iconDir + "/sys_startup.ico","sys_startup"),strErr);
|
||
createDesktopEntry(appDestPath,CDesktopEntry("hmi_explorer",QObject::tr("人机界面"),"open hmi",execPlatDir+"/hmi_explorer.sh"),strErr);
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
bool setSysctl()
|
||
{
|
||
system("echo 'net.ipv4.ping_group_range = 0 2147483647' > /etc/sysctl.d/555-ping.conf");
|
||
system("sysctl -p /etc/sysctl.d/555-ping.conf");
|
||
return true;
|
||
}
|
||
|
||
|
||
} //< namespace iot_sys
|
||
|
||
#endif //< #ifdef OS_LINUX
|
||
|
||
|