AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 451855
Accepted
SBF
SBF
Asked: 2018-06-26 13:14:13 +0800 CST2018-06-26 13:14:13 +0800 CST 2018-06-26 13:14:13 +0800 CST

/run/user/$UID 未在守护程序启动时挂载

  • 772

当我重新启动我的 Raspberry Pi (Stretch) 时,一个守护进程无法启动,因为/run/user/1000它不存在。这是我的单位文件:

[Unit]
Description=SBFspot Upload Daemon

[Service]
User=pi
Type=forking
TimeoutStopSec=60
ExecStart=/usr/local/bin/sbfspot.3/SBFspotUploadDaemon -p /run/user/1000/sbfspotupload.pid 2>&1> /dev/null
PIDFile=/run/user/1000/sbfspotupload.pid
Restart=no
RestartSec=15
SuccessExitStatus=SIGKILL

[Install]
WantedBy=default.target

重试几次后,当我配置为Restart=on-failure一切顺利时,但这并不是我真正想要的。我希望守护程序等待/run/user/1000安装。我试过了,After=run-user-1000.mount但它仍然失败。

这是可能的还是我必须坚持Restart=on-failure?

systemd systemd-unit
  • 1 1 个回答
  • 1776 Views

1 个回答

  • Voted
  1. Best Answer
    JdeBP
    2018-06-26T23:15:48+08:002018-06-26T23:15:48+08:00

    /run/user/1000,在用户 #1000 登录或显式启动 xyr 每用户服务管理之前,它当然不存在,这是一条红鲱鱼。使用它的整个机制不应该在那里。

    这个程序的错误 #215比你想象的要深得多。这个服务单元文件非常错误,程序本身的运行也是如此。有很多货物崇拜编程,基于对系统服务单元的基础知识的不了解。

    • 服务单元不是 shell 脚本。 systemd 手册确实解释了这一点。此处的ExecStart设置会导致服务程序使用一些额外的参数运行,2>&1>并且/dev/null.
    • 服务管理器已经确保只有一项服务运行。 这里添加的所有这些代码都是不必要的垃圾。
    • 不应该使用摇摇欲坠和危险的 PID 文件机制。 它在适当的服务管理中没有位置。
    • 服务管理器还处理在守护进程上下文中调用服务。基于 dæmonization 谬误, 其中的许多其他代码main()也是不必要的垃圾。
      • 程序根本不应该fork()运行,服务准备机制也不应该指定为Type=forking. 就像现实世界中的许多程序一样,这个程序一开始并没有说分叉准备协议。
      • 该程序已经以超级用户身份运行。 User=root是不必要的,实际上应该重新设计该服务,使其不需要以超级用户权限运行,而是在专用的非特权服务帐户的支持下运行。
      • 服务管理器已经在记录标准输出和错误,并且比这个程序做得更好。这个自制的日志系统只会增长一个日志文件,直到它填满整个文件系统,消耗为超级用户保留的所有紧急空间。
      • 您的日志只是标准错误,可以从 C++ 作为std::clog.
      • 事实上,从标准错误到重定向的所有代码fork()都不应该使用。服务管理处理所有这些,从会话领导到工作目录和 umask 再到标准 I/O,并正确处理。在服务管理器下使用时,该程序不会,也不应该尝试为自己做任何事情。

        你从 Boost 那里得到的一切都是错误的。

    • 三个服务单元是不必要的维护开销。 它们仅在After设置上有所不同,并且可以合并为一个。
    • 不优雅的终止不是成功。 鉴于在终止时清理文件已经SuccessExitStatus=SIGKILL存在一个问题,这是错误的。正常终止应该是优雅的,通过SIGTERM,并且SIGKILL应该被认为是异常的。(当然,整个output文件机制是一个糟糕实现的本土日志机制,不应该在服务管理下使用,正如已经解释的那样。)这是 systemd 的默认设置。
    • 数据库对象和其他东西的析构函数应该运行。 不要离开main()。exit()

    为在服务管理器下运行而正确实施的守护程序,无论是来自 daemontools、runit、s6、nosh、systemd 还是其他任何东西,都要短得多:

    … // 到这里为止都是一样的
    无效 pvo_upload(无效)
    {
        std::clog << "正在启动守护进程..." << std::endl;
    
        公共服务代码();
    
        std::clog << "正在停止守护进程..." << std::endl;
    }
    
    int main(int argc, char *argv[])
    {
        诠释 c;
        const char *config_file = "";
    
        /* 解析命令行 */
        而(1)
        {
            静态结构选项 long_options[] =
            {
                { "配置文件", required_argument, 0, 'c' },
                { 0, 0, 0, 0 }
            };
    
            int option_index = 0;
            c = getopt_long (argc, argv, "c:", long_options, &option_index);
    
            如果 (c == -1) 中断;
    
            开关 (c)
            {
                案例“c”:
                    config_file = optarg;
                    休息;
                默认:
                    返回 EXIT_FAILURE;
                    休息;
            }
        }
    
        if (cfg.readSettings(argv[0], config_file) != Configuration::CFG_OK)
            返回 EXIT_FAILURE;
    
        std::clog << "开始 SBFspotUploadDaemon 版本 " << VERSION << std::endl;
    
        // 检查数据库是否可访问
        db_SQL_Base db = db_SQL_Base();
        db.open(cfg.getSqlHostname(), cfg.getSqlUsername(), cfg.getSqlPassword(), cfg.getSqlDatabase());
        如果(!db.isopen())
        {
            std::clog << "无法打开数据库。检查配置。" << std::endl;
            返回 EXIT_FAILURE;
        }
    
        // 检查数据库版本
        int schema_version = 0;
        db.get_config(SQL_SCHEMAVERSION, schema_version);
        db.close();
    
        if (schema_version < SQL_MINIMUM_SCHEMA_VERSION)
        {
            std::clog << "将你的数据库升级到版本" << SQL_MINIMUM_SCHEMA_VERSION << std::endl;
            返回 EXIT_FAILURE;
        }
    
        // 安装我们的信号处理程序。
        // 这响应服务管理器发出停止服务的信号。
        信号(SIGTERM,处理程序);
    
        // 启动守护程序循环
        pvo_upload();
    
        返回 EXIT_SUCCESS;
    }
    

    服务单元也更短:

    [单元]
    描述=SBFspot 上传守护进程
    After=mysql.service mariadb.service network.target
    
    [服务]
    类型=简单
    TimeoutStopSec=10
    ExecStart=/usr/local/bin/sbfspot.3/SBFspotUploadDaemon
    重启=成功
    
    [安装]
    WantedBy=多用户.target
    

    systemctl status可以使用and journalctl(-u如果需要,使用选项和服务名称)查看日志输出。

    进一步阅读

    • 乔纳森·德博因·波拉德 (2016)。不要使用logrotate或newsyslog在本世纪。. 经常给出答案。
    • 乔纳森·德博因·波拉德 (2001)。 设计 Unix 守护程序时要避免的错误。经常给出答案。
    • 乔纳森·德博因·波拉德 (2015)。Unix 守护进程的就绪协议问题。经常给出答案。
    • https://unix.stackexchange.com/a/283739/5132
    • https://unix.stackexchange.com/a/321716/5132
    • 1

相关问题

  • journalctl 中的区分级别

  • 将默认编辑器更改为 vim for _ sudo systemctl edit [unit-file] _

  • systemd:如何在服务启动时运行脚本,而不编辑服务定义

  • 使用 systemd 看门狗支持重新启动应用程序

  • 使用键盘快捷键启动/停止 systemd 服务 [关闭]

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve