`flock` 在台式电脑上随机出现故障,但在笔记本电脑上却没有,可能是硬件有缺陷?

`flock` 在台式电脑上随机出现故障,但在笔记本电脑上却没有,可能是硬件有缺陷?

我正在使用下面的脚本对独占锁进行压力测试flock

在我的笔记本上,它总是运行良好。
但是当我在台式电脑上运行它时,它可能会随机失败,让两个实例同时运行(获取相同的锁!)。
两者都运行 ubuntu 20.04。

所以我怀疑我的桌面有硬件问题,可能是 RAM?

所以,我的问题是,根据 flock missbehavior 给我的提示,我如何跟踪/确定哪个硬件有缺陷?
我的意思是,flock 能指出哪个硬件有缺陷(或质量低劣)吗?

我如何确认问题:
我获取所有具有与完整路径脚本名称匹配的子命令的 flock 进程(即 flock 应作为子命令执行的命令)。
此外,我记录每个脚本完成的工作,并且在该日志中记录了两个或更多实例同时进行的工作。只有获取锁时才会记录工作。
我是否没有正确配置 flock 以提供独占/唯一锁?
我现在也在另一个终端上使用它:
while true;do date;lslocks |grep flock;sleep 1;done

剧本: cat >flock.tst.sh;chmod +x flock.tst.sh

#!/bin/bash

LC_NUMERIC=en_US.UTF-8

# HELPERS:
#trash /tmp/flock.tst.log;for((i=0;i<20;i++));do flock.tst.sh&:;done #run this on shell
#pkill -fe flock.tst.sh #end all concurrent children trying to acquire the lock
#while true;do date;lslocks |grep flock;sleep 1;done #use this to check if there is more than one lock acquired, check also the log file to confirm it, and if there is two subsequent WORK on the terminal log, it means a problem happened too

: ${bDaemonizing:=false}
: ${bReport:=false} #help use this to show more log, but will be harder to read it.
: ${bCheck:=false} #help this will let the script check if there is more than one instance working, but it may be slow and make it more difficult to let the problem happen
if ! $bDaemonizing;then
  echo "this IS a daemon script, only one instace runnable"
  flSelf="`realpath $0`"
  
  #set -x 
  while ! bDaemonizing=true flock --timeout=$(bc <<< "0.2+0.0$RANDOM") "$flSelf" "$flSelf" "$@";do
    if $bCheck;then
      strParents="$(nice -n 19 pgrep -f "^flock --timeout=.* $flSelf $flSelf" |tr '\n' ',' |sed -r 's"(.*),"\1"')"
      if [[ -n "$strParents" ]];then
        anDaemonPid=( $(nice -n 19 pgrep --parent "$strParents" -f "$flSelf") )
        if((${#anDaemonPid[*]}>1));then echo "ERROR: more than one daemon, flock failed!? :(";ps --no-headers -o ppid,pid,cmd -p "${anDaemonPid[@]}";fi
        if $bReport && ((${#anDaemonPid[*]}==1));then echo "$$:Wait daemon stop running or 'kill ${anDaemonPid[0]}'";fi #could be: "already running, exiting.", but the new instance may have updated parameters that work as intended now.
      fi
    fi
  done
  
  exit #returns w/e flock does
fi

echo "$$:Work:`date`"
for((i=0;i<60;i++));do
  echo "`\
    echo $i;\
    date;\
    ps --no-headers -o ppid,pid,stat,state,pcpu,rss,cmd -p "$PPID";\
    ps --no-headers -o ppid,pid,stat,state,pcpu,rss,cmd -p "$$";\
  `" >>/tmp/flock.tst.log
  
  sleep 1
done
echo "$$:Done:`date`"


一些结果:
如您所见,独占锁同时被进程 1458428(flock:1458427)和 1438949(flock:1438941)获取 :(

日志文件(由脚本创建)显示了此问题(在第 50 秒,发生了不应该获取锁的其他实例的第 2 秒日志):

2
Fri 22 Jan 17:03:16 -03 2021
1438953 1458427 S    S  0.0   784 flock --timeout=.22377 /home/myUser/bin/flock.tst.sh /home/myUser/bin/flock.tst.sh
1458427 1458428 S    S  0.0  3852 /bin/bash /home/myUser/bin/flock.tst.sh
50
Fri 22 Jan 17:03:16 -03 2021
1438925 1438941 S    S  0.0   788 flock --timeout=.229687 /home/myUser/bin/flock.tst.sh /home/myUser/bin/flock.tst.sh
1438941 1438949 S    S  0.0  3900 /bin/bash /home/myUser/bin/flock.tst.sh

lslockdate显示这一点(脚本上的while 与is 作为提示):

Fri 22 Jan 17:03:16 -03 2021
flock           1459088 FLOCK  1.8K WRITE* 0          0          0 /home/myUser/bin/flock.tst.sh
flock           1458427 FLOCK  1.8K WRITE  0          0          0 /home/myUser/bin/flock.tst.sh
flock           1438941 FLOCK  1.8K WRITE  0          0          0 /home/myUser/bin/flock.tst.sh (deleted)
Fri 22 Jan 17:03:17 -03 2021
flock           1459616 FLOCK  1.8K WRITE* 0          0          0 /home/myUser/bin/flock.tst.sh
flock           1458427 FLOCK  1.8K WRITE  0          0          0 /home/myUser/bin/flock.tst.sh
flock           1438941 FLOCK  1.8K WRITE  0          0          0 /home/myUser/bin/flock.tst.sh (deleted)

终端日志(产生了许多并发实例)显示以下内容:

1438949:Work:Fri 22 Jan 17:02:23 -03 2021
1458428:Work:Fri 22 Jan 17:03:14 -03 2021
1438949:Done:Fri 22 Jan 17:03:26 -03 2021
1476209:Work:Fri 22 Jan 17:04:02 -03 2021
1458428:Done:Fri 22 Jan 17:04:17 -03 2021

答案1

假设:就在事情发生之前,你保存了脚本。你的编辑器保存了一份副本,然后将副本移到了原始路径。参见Vim 如何做到这一点为什么

实际上,旧文件(inode)上仍保留着旧锁。这…/flock.tst.sh (deleted)在 的输出中显示为lslocks。但是flock,您的脚本(它的另一个实例?)不断生成使用该路径。当该路径开始指向另一个 inode 时,允许一些新文件flock获取新锁。这…/flock.tst.sh在 的输出中显示为lslocks

这两把锁是独立的,它们不能互相阻挡,因为它们使用不同的文件。Flock 按照设计运行。

我实际上可以通过运行脚本的两个实例(一个获取锁,另一个继续尝试获取锁)来重现您的结果,然后立即vim使用 ( ) 打开它。或者::w

cp flock.tst.sh foo
mv foo flock.tst.sh

相关内容