Shell

sh:其中:第 1 行:語法錯誤:文件意外結束;sh:為“which”導入函式定義時出錯

  • December 16, 2021

我們正在執行:Red Hat Enterprise Linux 版本 8.5 (Ootpa)。我們允許伺服器使用“yum -y update”每週更新一次。我們最近在執行 shell 命令時開始收到以下錯誤:

  • sh:其中:第 1 行:語法錯誤:文件意外結束
  • sh:為“which”導入函式定義時出錯

我不知道我們所做的任何更改可能會導致此錯誤——這就是我指向 yum 系統更新的原因。我們的大部分程式碼都是用 php 編寫的,我們使用 passthru() 來執行 shell 命令。當我們很少編寫 shell 腳本時,我們通常使用 bash。

在執行使用 passthru() 的 php 腳本之前,我有能力使用“unset which”來防止這些錯誤。我們從許多腳本執行許多 shell 命令。更新這些腳本中的每一個都不是一個有效的解決方案——既費時又可能引入缺陷。

有趣的是,以下程式碼不會導致錯誤:

#!/bin/sh
echo hello

有沒有辦法在系統或使用者級別“取消設置”一次,這樣每次我們執行 shell 時都會執行它?也許有一個我可以更改的外殼配置文件或類似的東西。

更新 1

我在 /etc/profile.d/which2.sh 中找到了以下內容

# shellcheck shell=sh
# Initialization script for bash, sh, mksh and ksh

which_declare="declare -f"
which_opt="-f"
which_shell="$(cat /proc/$$/comm)"

if [ "$which_shell" = "ksh" ] || [ "$which_shell" = "mksh" ] || [ "$which_shell" = "zsh" ] ; then
 which_declare="typeset -f"
 which_opt=""
fi

which ()
{
(alias; eval ${which_declare}) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot "$@"
}

export which_declare
export ${which_opt} which

語法在這裡看起來是正確的。我可以說它導出了“哪個”——但我不知道為什麼。如果我知道這是做什麼的,我可以評估unset which.

更新 2

創建了一個小的 php 腳本:

#!/usr/bin/php
<?php
passthru('echo hello');
?>

這確實會產生錯誤。

我將unset which.bashrc 作為解決方法。這適用於 bash 和 php。今天早上我評論了unset which來自 .bashrc 的內容。問題不再存在。我相信這個問題是由上游程式碼更改創建和解決的。謝謝@ilkkachu!

錯誤消息提示通過環境將 shell 函式導出和導入子 shell 的 Bash 特性。它讀取名稱以、 開頭的環境變數,並嘗試將它們解析為函式定義。BASH_FUNC_*funcname*%%``() {

該錯誤表示定義有問題,您可以通過例如缺少結束來得到它}() { echo hi;在這裡,當 Bash 看到它時,環境變數將包含該字元串:

$ perl -e '$ENV{"BASH_FUNC_which%%"} = "() { echo hi;"; exec("/bin/bash")'
bash: which: line 1: syntax error: unexpected end of file
bash: error importing function definition for `which'

unset which將取消定義函式,因此它不會被導出,但這並不能解釋為什麼從 PHP 啟動 shell 時定義會被破壞。我不確定 PHP 或您的 PHP 程序對環境變數做了什麼,但可能的原因是 Bash 在 envvars 中使用換行符來導出函式。例如:

$ which() { echo hi; } 
$ export -f which
$ env |grep which -A1
BASH_FUNC_which%%=() {  echo hi
}

如果只看第一行,定義就會被破壞,就像我上面的 Perl 腳本一樣。你可能想調查一下。

至於which函式是從哪裡來的,看shell的初始化文件,ie/etc/bash.bashrc等。見如何確定環境變數來自哪裡?,它們也應該適用於功能。(懶惰的第一次嘗試grep -re which /etc:)

引用自:https://unix.stackexchange.com/questions/681482