为什么从脚本调用的汇编程序在从 crontab 运行时不创建某个文件?

为什么从脚本调用的汇编程序在从 crontab 运行时不创建某个文件?

我在用着这个脚本构建和打包我开发的一些应用程序。脚本的完整内容列在最后。

它由这个 crontab 条目调用:50 23 * * * nice $HOME/update-dl-wwwecm $HOME | tee -a $HOME/build-dl-wwwecm/log

为了调试,我将脚本复制到测试目录~/test/20211101/t/并对其进行了轻微编辑。 (就像删除脚本末尾硬编码的一些包一样。)我还手动mkdir build-dl-wwwecmmkdir webrepos此测试目录中并将hg clone以下存储库放入webrepos子目录中:

  1. lmacros 宏集合(构建任何其他库都需要这个。并且它应该被列为第一个要更新的存储库。)

  2. l时钟应用

  3. KEEPHOOK实用程序

  4. SHUFHOOK实用程序

接下来,我在 crontab 中添加了一个“每分钟”行,如下所示:* * * * * nice $HOME/test/20211101/t/update-dl-wwwecm $HOME/test/20211101/t | tee -a $HOME/test/20211101/t/build-dl-wwwecm/log

更新脚本检查来自 webrepos 子目录中的存储库的传入提交。然后,它会提取新的提交,并且对于mak.sh在构建目录树中找到的每个脚本文件,它会更改为该文件的目录并运行该文件。这是mak.shKEEPHOOK 的完整内容

#! /bin/bash
nasm -I ../lmacros/ -f bin transien.asm -l keephook.lst -o keephook.com "$@"

现在我观察到的是,如果我自己以用户身份登录(通过 ssh,在屏幕内运行 bash,使用 ConnectBot 应用程序连接到服务器)调用更新脚本,那么一切都会按预期工作。命令如下所示:(hg -R build-dl-wwwecm/keephook strip tip因此更新脚本将找到要拉取的新提交)然后./update-dl-wwwecm "$PWD"(实际执行更新,并将 BASE 的参数指定为测试目录)。

但是,如果从 crontab 调用相同的脚本,则有一件事会有所不同:NASM 似乎会删除然后不创建输出文件keephook.com- 尽管它确实创建了一个keephook.lst看起来完整的列表文件。日志文件中未发现错误或警告。所有其他应用程序都构建得很好。

为什么会这样以及如何解决?


这是完整的更新脚本:

#! /bin/bash

# Usage of the works is permitted provided that this
# instrument is retained with the works, so that any entity
# that uses the works is notified of this instrument.
#
# DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

BASE="$1"
if [[ -z "$BASE" ]]
then
  echo "Error: No base specified." >&2
  exit 1
fi
SDIR="$BASE"/webrepos
[[ -n "$2" ]] && BASE="$2"
BDIR="$BASE"/build-dl-wwwecm
TDIR="$BASE"/wwwecm/download
ODIR="$BASE"/wwwecm/download/old

[[ ! -d "$BDIR" ]] && mkdir -p "$BDIR"
[[ ! -d "$TDIR" ]] && mkdir -p "$TDIR"
[[ ! -d "$ODIR" ]] && mkdir -p "$ODIR"

function update() {
    # $1 = path below BDIR
    # $2 = "-r" if there is a branch
    # $3 = branch name if there is a branch
  if [[ ! -d "$BDIR"/"$1" ]]
  then
    hg init "$BDIR"/"$1"
  fi
  cd "$BDIR"/"$1"
  if var="$(hg incoming "$SDIR"/"$1" $2 $3)"; then
    echo "$var"
    hg pull "$SDIR"/"$1" $2 $3 && hg up $3
    find . -name mak.sh -print0 | \
      ONE="$1" xargs -r0 bash -c \
        'for file; do echo === "$ONE"/"$file"; (cd "${file%/*}"; "./${file##*/}"); done' scriptlet
    if [[ -f "$TDIR"/"$1".zip ]]
    then
      [[ ! -d "$ODIR"/"$1" ]] && mkdir -p "$ODIR"/"$1"
      datestamp="$(date -r "$TDIR"/"$1".zip +%Y%m%d)"
      echo === mv --backup=numbered "$TDIR"/"$1".zip "$ODIR"/"$1"/"$datestamp".zip
      mv --backup=numbered "$TDIR"/"$1".zip "$ODIR"/"$1"/"$datestamp".zip
    fi
    echo === zipping "$1"
    7za a -mm=deflate -mx=9 -tzip "$TDIR"/"$1".zip *
  fi
}

update lmacros
update keephook
update shufhook
update rxansi
update lclock
update seekext
update tsr
update fdapm
update renumber
touch "$BDIR"/lastrun

答案1

在编写问题时弄清楚了:我没有将 mak 脚本的 stderr 重定向到 stdout,因此在使用tee. (它是在来自 cron 和汇编程序列表文件的电子邮件中找到的,但我之前没有想到检查其中任何一个是否有错误消息。我还错误地认为 NASM 会在出现错误时删除列表文件。)

以用户身份运行和从 crontab 运行之间的奇怪差异归结为根据路径使用不同的 NASM 版本:NASM version 2.14对于 crontab,NASM version 2.15.03 compiled on Dec 28 2020对于我的 shell 会话。他们的不同之处在于lea di条指令使用该word关键字会被旧版本拒绝,但会被新版本允许。

更新脚本的修复是添加2>&1重定向到运行 make 脚本的命令。

相关内容