【问题标题】:`ln -s` in a script acts as `cp`脚本中的 ln -s 充当 cp
【发布时间】:2014-11-27 07:17:51
【问题描述】:

问题

我有这个 bash 脚本:

ACTIVE_DB=$(grep -P "^[ \t]*db.active" config.properties | cut -d= -f2 | tr -s " ")
echo $ACTIVE_DB
if [ "$ACTIVE_DB" = "A" ]
then
    ln -sf config-b.properties config.properties
else
    ln -sf config-a.properties config.properties
fi

config-a.properties

db.active = A

config-b.properties

db.active = B

当我运行脚本时,会执行硬拷贝 (=cp),config.properties 通常不是符号链接(也不是物理链接),而是与 @ 内容相同的全新文件987654326@或config-b.properties

$ ls -li
53 -rw-r--r-- 1 ogregoir ogregoir     582 Sep 30 15:41 config-a.properties
54 -rw-r--r-- 1 ogregoir ogregoir     582 Sep 30 15:41 config-b.properties
56 -rw-r--r-- 1 ogregoir ogregoir     582 Oct  2 11:28 config.properties

当我在提示符中逐行手动运行时,我没有遇到任何问题,并且确实总是会创建一个符号链接,并且config.properties 指向config-a.propertiesconfig-b.properties

$ ls -li
53 -rw-r--r-- 1 ogregoir ogregoir     582 Sep 30 15:41 config-a.properties
54 -rw-r--r-- 1 ogregoir ogregoir     582 Sep 30 15:41 config-b.properties
55 lrwxrwxrwx 1 ogregoir ogregoir      20 Oct  2 11:41 config.properties -> config-b.properties

注意事项

  • 在其他任何地方都没有打开任何文件(我是唯一的活动用户,并且使用该配置的应用程序没有运行)。
  • 有时ln -sf 行为正常,但通常的规则是制作硬拷贝。
  • 脚本从另一个目录运行,但在执行此处操作之前,cds 到config*.properties 文件所在的目录。
  • 脚本要长得多,但这是重现错误的最短示例。
  • bash 版本是 4.1.2(它是本地的,所以我不关心 shellshock)。
  • ln 版本为 8.4。
  • 操作系统:Red Hat Enterprise Linux Server 6.5 版(圣地亚哥)。
  • 用于该文件夹的文件系统:ext4。

问题

  • 为什么我的脚本没有始终如一地创建符号链接,而是制作了硬拷贝?
  • 如何在此处强制使用符号链接?

【问题讨论】:

  • ln 命令将不会创建副本。从不
  • 是的,我可以阅读man ln,但它确实...随机!
  • 抱歉,我无法通过 RHEL6.0 和 100.000 更改链接重现此问题:cp /etc/passwd /tmp/config-a.properties; cp /etc/passwd /tmp/config-b.properties; cd /tmp; c=0; while true; do ln -sf config-a.properties config.properties; [ ! -h config.properties ] && exit; ln -sf config-b.properties config.properties; [ ! -h config.properties ] && exit; echo $c; c=$((c+1)); done
  • 在每次调用之前添加command -v ln 以显示ln 实际调用的内容(以排除shell 函数或像/this/is/wrong/ln 这样的意外二进制文件)。由于符号链接的目标甚至不需要存在,因此前面的命令不太可能对您正在观察的内容产生任何影响。
  • 我怀疑您有一些其他脚本或代码正在覆盖符号链接。例如,sed -i 将删除符号链接。有多种命令和实用程序可以通过创建副本、修改副本、然后将副本移动到原始文件之上来修改文件,这会破坏原始符号链接。或者另一种解释:您没有运行您认为的脚本,或者没有修改您认为的文件。

标签: bash cp ln rhel6


【解决方案1】:

我怀疑您有一些其他脚本或代码覆盖了符号链接。例如,sed -i 将删除符号链接。有多种命令和实用程序可以通过创建副本、修改副本、然后将副本移动到原始文件之上来修改文件,这会破坏原始符号链接。

【讨论】:

  • 确实如此。我检查了有无sed -i,结果不同。非常感谢!我不认为它会替换文件,所以我把它留在了我的小测试中,但没有在问题中复制/粘贴它。对不起。
  • 我现在使用sed --follow-symlinks -i,而我的脚本正是我想要的。谢谢!
  • 这:sed -i "$(realpath ./config.properties)" 也可以通过(完全)解析文件来工作。 https://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script
【解决方案2】:

该问题的唯一可能答案(如所问):为什么ln 表现得像cp 是:它不能。

唯一可能的答案是:您提供给我们的内容并不完全是正在执行的内容,或者正在运行的其他脚本会改变答案。

一些可能的替代方案:
1.- ln 命令实际上是在做一个硬链接。 i-node 列表 (ls -li) 确认 i-node 编号是不同的。所以,不,这不是原因。

2.- ln 有别名或函数吗?
这很容易检查。只需在 Bash 中发出 type -a ln 即可。结果将显示 bash 将 ln 解释为什么。如果它只是文件/bin/ln,那么它是正确的。
您确认不涉及别名或函数。

3.- 因为“脚本是从另一个目录运行的”。 这里的要点是:文件系统中是否有其他文件具有相同的 i 节点号(如果 ln 实际上正在创建硬链接)。可以验证是否存在具有相同 i 节点的其他文件(使用列表中的 i 节点编号 53、54、56):

find / -follow -inum <your inum>

4.- 我希望您真正意识到config-b.properties 实际上并不存在(作为文件)。编辑此类文件可能会破坏链接。

实际执行的脚本是否也在更改/更新文件内容?

Note01:请注意,K 技巧仅通过一个外部调用即可解决提取问题: http://www.charlestonsw.com/perl-regular-expression-k-trick/

ACTIVE_DB=$(grep -Po "^[ \t]*db.active[ ]+=[ ]+\K." config.properties)

已经确认,在实际执行的脚本后面的sed -iconfig-b.properties 是问题的根源。

【讨论】:

  • 关于引号,我知道剪切的结果是“A”。这就是我后来修剪它的原因。其余的,我会在我回来工作时检查一下。感谢您提供一些见解。
  • type -a ln 的结果是ln is /bin/ln。对我来说似乎没问题。我在问题中显示的 sn-ps 是从我的脚本和配置文件中获取的。我们确实有我们称之为AB 的数据库,它们可以相互替换。最后,我不明白你的第二点。你能详细说明一下吗?
  • 命令“ln”无法执行您报告的操作。应该有别的事情发生。我将编辑我的答案以提供更多选项。
猜你喜欢
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 2010-11-02
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 1970-01-01
  • 2018-04-06
相关资源
最近更新 更多