【发布时间】:2010-09-09 20:38:42
【问题描述】:
我曾经读到,在 shell 中为临时文件获取唯一文件名的一种方法是使用双美元符号 ($$)。这确实会产生一个不时变化的数字......但如果你重复调用它,它会返回相同的数字。 (解决办法就是利用时间。)
我很想知道$$ 究竟是什么,以及为什么建议将其作为生成唯一文件名的一种方式。
【问题讨论】:
我曾经读到,在 shell 中为临时文件获取唯一文件名的一种方法是使用双美元符号 ($$)。这确实会产生一个不时变化的数字......但如果你重复调用它,它会返回相同的数字。 (解决办法就是利用时间。)
我很想知道$$ 究竟是什么,以及为什么建议将其作为生成唯一文件名的一种方式。
【问题讨论】:
$$ 是 bash 中的进程 ID (PID)。使用$$ 是个坏主意,因为它通常会产生竞争条件,并允许您的shell 脚本被攻击者破坏。例如,查看所有创建不安全临时文件并不得不发布安全建议的 these people。
改为使用mktemp。 Linux man page for mktemp 非常棒。以下是其中的一些示例代码:
tempfoo=`basename $0`
TMPFILE=`mktemp -t ${tempfoo}` || exit 1
echo "program output" >> $TMPFILE
【讨论】:
mktemp 选项 -t 现在已弃用(我认为是因为 char - 存在问题)。 这些天使用mktemp ${tempfoo}.XXXXXX。我冒昧地更新您的帖子。
TMPFILE=$(mktemp)。
在 Bash 中,$$ 是进程 ID,如 cmets 中所述,由于各种原因,将其用作临时文件名并不安全。
对于临时文件名,使用mktemp 命令。
【讨论】:
$$是当前进程的id。
【讨论】:
类 UNIX 操作系统中的每个进程都有一个(临时)唯一标识符,即 PID。同时运行的两个进程不能有相同的PID,$$指的是运行脚本的bash实例的PID。
这非常不是一个唯一标识符,因为它永远不会被重用(实际上,PID 会不断重用)。它给你的是一个数字,这样,如果另一个人运行你的脚本,他们将在你的脚本仍在运行时获得不同的标识符。一旦你的 PID 死了,PID 可能会被回收,其他人可能会运行你的脚本,获得相同的 PID,从而获得相同的文件名。
因此,说“$$ 给出一个文件名,这样如果其他人在我的实例仍在运行的情况下运行相同的脚本,他们将获得不同的名称”,这真的很明智。
【讨论】:
$$ 是您的 PID。它不会真正生成一个唯一的文件名,除非你很小心并且没有其他人以完全相同的方式这样做。
通常你会创建类似 /tmp/myprogramname$$
有很多方法可以解决这个问题,如果您正在写入其他人可以写入的位置,那么在许多操作系统上预测您将拥有什么 PID 并搞砸并不太困难 - 想象一下您' 以 root 身份运行,我创建 /tmp/yourprogname13395 作为指向 /etc/passwd 的符号链接——然后你写入它。
在 shell 脚本中这样做是一件坏事。如果你打算使用临时文件来做某事,你应该使用更好的语言,它至少可以让你添加“独占”标志来打开(创建)文件。然后你可以确定你没有破坏其他东西。
【讨论】:
$$ 是运行脚本的 shell 解释器的 pid(进程 ID)。目前在系统上运行的每个进程都是不同的,但是随着时间的推移,pid 会回绕,并且在您退出后最终会有另一个具有相同 pid 的进程。只要您正在运行,pid 对您来说是唯一的。
从上面的定义应该很明显,无论你在脚本中使用多少次 $$,它都会返回相同的数字。
您可以使用,例如/tmp/myscript.scratch.$$ 作为不需要非常可靠或安全的东西的临时文件。最好在脚本末尾删除此类临时文件,例如使用 trap 命令:
trap "echo 'Cleanup in progress'; rm -r $TMP_DIR" EXIT
【讨论】:
$$ 是当前 shell 进程的 pid。这不是生成唯一文件名的好方法。
【讨论】:
这是 bash 进程的进程 ID。任何并发进程都不会拥有相同的 PID。
【讨论】:
$$ 是运行脚本的 shell 的进程 ID。有关更多详细信息,请参阅 sh 或 bash 的手册页。可以使用命令行“man sh”或在网上搜索“shell manpage”找到手册页
【讨论】:
让我再说一遍 emk 的答案——不要将 $$ 本身用作“独特”的任何东西。对于文件,使用 mktemp。对于同一 bash 脚本中的其他 ID,请使用“$$$(date +%s%N)”以获得合理良好的唯一性。
-k
【讨论】:
另外,您可以通过此命令获取登录用户名。例如。
echo $(</proc/$$/login id). After that, you need to use getent command.
【讨论】:
在 Fish 外壳 (3.1.2) 中:
$符号也可以多次使用,作为一种“取消引用”运算符(C 或 C++ 中的 *)
set bar bazz
set foo bar
echo $foo # bar
echo $$foo # same as echo $bar → bazz
【讨论】: