飞机总是在地面加油吗?

飞机总是在地面加油吗?

在 Ubuntu 中,

  • 运行可执行文件或者脚本文件时,如果移动或者重命名该文件,会不会影响运行?

  • 运行 Windows 可执行文件时(例如PDFXC查看器) 在 wine 下,移动或者重命名 Windows 可执行文件是否会影响其在 wine 下的运行?

谢谢。

答案1

飞机总是在地面加油吗?

当然你会这么想。但是 0.001% 的时间它们在空中加油。例如军事应用。所以这个规则并不牢固。可执行文件和脚本也是如此。例如,病毒会在可执行文件运行时感染它们,也会感染磁盘上的副本。如果它们崩溃了,那是一件好事。但是非病毒也可以更新可执行文件/脚本。

自我更新的脚本示例

此脚本:如何让脚本在单独的文件中记录其执行的次数?根据已运行的次数进行更新。

传统上,每个脚本文件都使用一个单独的配置文件来记录其运行次数。但是,如果您有几十个脚本,则将运行次数存储在脚本本身中是有意义的。此外,您不必跟踪配置文件的存储位置,也不必在配置文件移动时更改脚本。修改运行次数的代码可以包含在或sourcebash.命令中,以降低维护成本并提高可读性。

代码片段

以下是上面链接中的相关代码:

# This script run count: 0

[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :
#     This is useful boilerplate code for shell scripts.  Put it at the top  of
#     the  shell script you want to lock and it'll automatically lock itself on
#     the first run.  If the env var $FLOCKER is not set to  the  shell  script
#     that  is being run, then execute flock and grab an exclusive non-blocking
#     lock (using the script itself as the lock file) before re-execing  itself
#     with  the right arguments.  It also sets the FLOCKER env var to the right
#     value so it doesn't run again.

# Read this script with entries separated newline " " into array
mapfile -t ScriptArr < "$0"

# Build search string that cannot be named
SearchStr="This script"
SearchStr=$SearchStr" run count: "

# Find our search string in array and increment count
for i in ${!ScriptArr[@]}; do
    if [[ ${ScriptArr[i]} = *"$SearchStr"* ]]; then
        OldCnt=$( echo ${ScriptArr[i]} | cut -d':' -f2 )
        NewCnt=$(( $OldCnt + 1 ))
        ScriptArr[i]=$SearchStr$NewCnt
        break
    fi
done

# Rewrite our script to disk with new run count
# BONUS: Date of script after writing will be last run time
printf "%s\n" "${ScriptArr[@]}" > "$0"

代码解析

我将快速解释一下独特代码部分的工作原理。

mapfile -t ScriptArr < "$0"

^ 这会将整个脚本读/script/path/script-name.sh入名为 的数组中ScriptArr

OldCnt=$( echo ${ScriptArr[i]} | cut -d':' -f2 )
NewCnt=$(( $OldCnt + 1 ))
ScriptArr[i]=$SearchStr$NewCnt

^ 这将获取注释行中的旧计数:# This script run count: 0并将其加 1。

printf "%s\n" "${ScriptArr[@]}" > "$0"

^ 这会将修改后的脚本数组作为新的可执行脚本写入磁盘。一个好的(或坏的)副作用是脚本上次运行的日期现在是脚本的修改日期。

多用户注意事项

注意FLOCKER上面命令中的变量:

[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :

^ 这是针对多个用户的。如果一个用户正在运行脚本,它会阻止第二个用户运行同一个脚本。假设您等到第一个用户的工作结束,然后移动脚本。这很糟糕,因为处于等待模式的第二个用户现在可以访问运行脚本,因为信号量锁被丢弃了。然而,在第一个用户的工作完成后,您将脚本移动到了另一个目录。99.999% 的时间都不是大问题,但在极少数情况下,会出现无法理解的错误。

概括

正在运行的脚本或可执行文件可以改变自身,甚至可以改变同一应用程序中未运行的另一个程序。

一般来说,移动(即重命名)正在运行的程序是 99% 安全的。不过我永远不会这么做。

您的问题是关于wine(伪 Windows)的,但这些 bash 脚本是为 Linux 下的 Ubuntu 和 Windows 下的 Ubuntu(WSL)设计的。重点不在于此,wine而在于展示在编程/脚本世界中可以做什么。

相关内容