【问题标题】:Broken symlinks and a mysterious (deleted)损坏的符号链接和一个神秘的(已删除)
【发布时间】:2014-06-04 14:04:42
【问题描述】:

我一直在使用 linux 上的 proc 文件系统做一些事情,我遇到了一些我想澄清的行为。

/proc 中的每个进程都有一个指向其可执行文件/proc/{pid}/exe 的符号链接。如果一个进程在其可执行文件被删除后继续运行,读取此符号链接将返回可执行文件的路径,并在末尾附加(deleted)

运行此命令,您甚至可能会在系统上看到一些命令:

grep '(deleted)' <(for dir in $(ls /proc | grep -E '^[0-9]+'); do echo "$dir $(readlink /proc/$dir/exe)"; done)

我尝试使用一些简单的 bash 命令重新创建此行为:

>>> echo "temporary file" >> tmpfile.test
>>> ln -s tmpfile.test tmpfile.link
>>> rm tmpfile.test
>>> readlink tmpfile.link
tmpfile.test

名字后面没有(deleted)!尝试cat tmpfile.link 确认链接已损坏 (cat: tmpfile.link: No such file or directory)。

但是,前几天,同样的测试确实导致(deleted) 被附加到 readlink 的输出中。什么给了?

这是我想知道的:

  • 是否有一系列事件可以保证(deleted) 将 附加到名称后?
  • 为什么/proc/{pid}/exe 显示(deleted) 用于删除的可执行文件?
  • 如何通过/proc/{pid}/exe获取可执行文件的名称 没有任何附加 (deleted) 并保证原始 可执行文件不只是命名为some_executable (deleted)

【问题讨论】:

    标签: linux bash symlink procfs


    【解决方案1】:

    FWIW,特殊的&lt;filename&gt; (deleted) 行为在Linux 内核函数d_path() 中实现:https://elixir.bootlin.com/linux/v4.1.13/source/fs/dcache.c#L3080

    源 cmets(在下面的 sn-p 中)表明特殊行为仅适用于为某些“合成文件系统”(例如 procfs)和“伪 inode”动态生成的名称(路径)。

    /**
     * d_path - return the path of a dentry
     * @path: path to report
     * @buf: buffer to return value in
     * @buflen: buffer length
     *
     * Convert a dentry into an ASCII path name. If the entry has been deleted
     * the string " (deleted)" is appended. Note that this is ambiguous.
     *
     * Returns a pointer into the buffer or an error code if the path was
     * too long. Note: Callers should use the returned pointer, not the passed
     * in buffer, to use the name! The implementation often starts at an offset
     * into the buffer, and may leave 0 bytes at the start.
     *
     * "buflen" should be positive.
     */
    char *d_path(const struct path *path, char *buf, int buflen)
    {
        char *res = buf + buflen;
        struct path root;
        int error;
    
        /*
         * We have various synthetic filesystems that never get mounted.  On
         * these filesystems dentries are never used for lookup purposes, and
         * thus don't need to be hashed.  They also don't need a name until a
         * user wants to identify the object in /proc/pid/fd/.  The little hack
         * below allows us to generate a name for these objects on demand:
         *
         * Some pseudo inodes are mountable.  When they are mounted
         * path->dentry == path->mnt->mnt_root.  In that case don't call d_dname
         * and instead have d_path return the mounted path.
         */
        if (path->dentry->d_op && path->dentry->d_op->d_dname &&
            (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))
            return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
    
        rcu_read_lock();
        get_fs_root_rcu(current->fs, &root);
        error = path_with_deleted(path, &root, &res, &buflen);
        rcu_read_unlock();
    
        if (error < 0)
            res = ERR_PTR(error);
        return res;
    }
    

    【讨论】:

      【解决方案2】:

      不是readlink,而是Linux将符号链接更改为指向&lt;filename&gt; (deleted),即(deleted)被附加到链接的目标。

      【讨论】:

      • 不是我正在寻找的答案,但它让我朝着正确的方向前进。
      猜你喜欢
      • 2014-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-14
      • 1970-01-01
      • 2013-11-24
      相关资源
      最近更新 更多