"read" 后无法识别变量
Variable not being recognized after "read"
-- 编辑:已解决。查看答案。
背景:
我正在编写一个 shell,当有人调整数据库大小时,它将执行我们系统所需的一些额外操作。
shell 是用 ksh (要求)编写的, OS 是 Solaris 5.10 。
问题在于其中一项检查,它验证底层 OS.
上有足够的空闲 space
问题:
检查读取 root 的 df -k 行,这是我在此步骤中检查的内容,并将其打印到文件中。然后我 "read" 将内容放入我在计算中使用的变量中。
不幸的是,当我尝试对其中一个变量进行 运行 算术运算时,我收到一条错误消息,指示它为空。我在该行之后放置的调试输出行验证它是否为空...它失去了它的价值...
我已经尝试了所有可以在网上找到的执行此操作的方法,当我手动 运行 时它们有效,但在 shell 文件中无效。
(* 文件确实有 #!/usr/bin/ksh)
代码:
df -k | grep "rpool/ROOT" > dftest.out
RPOOL_NAME=""; declare -i TOTAL_SIZE=0; USED_SPACE=0; AVAILABLE_SPACE=0; AVAILABLE_PERCENT=0; RSIGN=""
read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN < dftest.out
\rm dftest.out
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN
((TOTAL_SIZE=$TOTAL_SIZE/1024))
这是结果:
DBResize.sh[11]: TOTAL_SIZE=/1024: 语法错误
我现在正在紧张,如有任何帮助,我们将不胜感激。
对于那些感兴趣的人,我发现不可能像我那样使用 "read"。
"read" 分配的变量值只是 "do not last".
为了解决这个问题,我应用了使用标准 "while read" 格式的不太理想的解决方案,并在循环内将所选变量回显到变量文件中。
一旦创建了所述文件,我就 "loaded" 它。
(伪代码:)
LOOP START
echo "VAR_A="$VAR_A"; VAR_B="$VAR_B";" > somefile.out
LOOP END
. somefile.out
奇怪...当我删除您的 "declare" 行时,您的原始代码似乎运行良好(至少在 Linux 上使用 ksh)
代码:
#!/bin/ksh
df -k | grep "/home" > dftest.out
read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN < dftest.out
\rm dftest.out
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN
((TOTAL_SIZE=$TOTAL_SIZE/1024))
print $TOTAL_SIZE
结果:
32962416 5732492 25552588 19% /home
5598
简单的 df -k 返回的值是多少。变量似乎会持续。
您 post 编写的代码无法生成您 post 编写的输出。最明显的是,错误在第 11 行发出信号,但您 post 编辑的代码少于 11 行。前面几行可能很重要。当您寻求帮助时总是 post complete code。
更具体地说,ksh 中不存在 declare
命令,它是 bash 的东西。您可以使用 typeset
获得相同的结果(declare
是等同于 typeset
的 bash,但并非所有选项都相同)。您正在使用 bash 执行此脚本,或者存在关于 declare
的另一条错误消息,或者您已经定义了一些其他命令,包括 declare
,这可能会改变此代码的行为。
然而,None 应该会对您 post 遇到的特定问题产生影响。由 read
创建的变量保持赋值直到子 shell 结束,即直到代码命中 )
,管道的末端(管道的左侧仅在ksh)等
关于 declare
或 typeset
的使用,请注意,您只是将 TOTAL_SIZE
声明为整数。对于其他变量,您只需分配一个恰好仅由数字组成的值。这与您 post 编辑的代码无关,但它可能不是您的意思。
可能发生的一件事是 grep
不匹配任何内容,因此 read
读取空行。您应该检查错误。在脚本中使用 set -e
以在第一个错误时退出。 (有些情况下 set -e
没有捕捉到错误,但这是一个好的开始。)
可能发生的另一件事是 df
将其输出分成多行,因为包含文件系统名称的第一列太大。为防止这种分裂,传递选项 -P
.
使用临时文件是脆弱的:代码可能在只读目录中执行,另一个进程可能想同时访问同一个文件...这里临时文件是没有用的。只需直接通过管道输入 read
。在 ksh 中(与包括 bash 在内的大多数其他 sh 变体不同),管道的右侧在主 shell 中运行,因此对管道右侧变量的赋值在以下命令。
在此特定脚本中无关紧要,但您可以在算术表达式中使用不带 $
的变量。使用 $
替换可能会产生混乱结果的字符串,例如a='1+2'; $((a*3))
扩展为 7
。不使用 $
使用数值(在 ksh 中,a='1+2'; $((a*3))
扩展为 9
;在某些 sh 实现中,您会得到一个错误,因为 a
的值不是数字)。
#!/usr/bin/ksh
set -e
typeset -i TOTAL_SIZE=0 USED_SPACE=0 AVAILABLE_SPACE=0 AVAILABLE_PERCENT=0
df -Pk | grep "rpool/ROOT" | read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN
((TOTAL_SIZE=TOTAL_SIZE/1024))
-- 编辑:已解决。查看答案。
背景: 我正在编写一个 shell,当有人调整数据库大小时,它将执行我们系统所需的一些额外操作。 shell 是用 ksh (要求)编写的, OS 是 Solaris 5.10 。 问题在于其中一项检查,它验证底层 OS.
上有足够的空闲 space问题: 检查读取 root 的 df -k 行,这是我在此步骤中检查的内容,并将其打印到文件中。然后我 "read" 将内容放入我在计算中使用的变量中。 不幸的是,当我尝试对其中一个变量进行 运行 算术运算时,我收到一条错误消息,指示它为空。我在该行之后放置的调试输出行验证它是否为空...它失去了它的价值...
我已经尝试了所有可以在网上找到的执行此操作的方法,当我手动 运行 时它们有效,但在 shell 文件中无效。 (* 文件确实有 #!/usr/bin/ksh)
代码:
df -k | grep "rpool/ROOT" > dftest.out
RPOOL_NAME=""; declare -i TOTAL_SIZE=0; USED_SPACE=0; AVAILABLE_SPACE=0; AVAILABLE_PERCENT=0; RSIGN=""
read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN < dftest.out
\rm dftest.out
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN
((TOTAL_SIZE=$TOTAL_SIZE/1024))
这是结果:
DBResize.sh[11]: TOTAL_SIZE=/1024: 语法错误
我现在正在紧张,如有任何帮助,我们将不胜感激。
对于那些感兴趣的人,我发现不可能像我那样使用 "read"。
"read" 分配的变量值只是 "do not last".
为了解决这个问题,我应用了使用标准 "while read" 格式的不太理想的解决方案,并在循环内将所选变量回显到变量文件中。
一旦创建了所述文件,我就 "loaded" 它。
(伪代码:)
LOOP START
echo "VAR_A="$VAR_A"; VAR_B="$VAR_B";" > somefile.out
LOOP END
. somefile.out
奇怪...当我删除您的 "declare" 行时,您的原始代码似乎运行良好(至少在 Linux 上使用 ksh)
代码:
#!/bin/ksh
df -k | grep "/home" > dftest.out
read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN < dftest.out
\rm dftest.out
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN
((TOTAL_SIZE=$TOTAL_SIZE/1024))
print $TOTAL_SIZE
结果:
32962416 5732492 25552588 19% /home
5598
简单的 df -k 返回的值是多少。变量似乎会持续。
您 post 编写的代码无法生成您 post 编写的输出。最明显的是,错误在第 11 行发出信号,但您 post 编辑的代码少于 11 行。前面几行可能很重要。当您寻求帮助时总是 post complete code。
更具体地说,ksh 中不存在 declare
命令,它是 bash 的东西。您可以使用 typeset
获得相同的结果(declare
是等同于 typeset
的 bash,但并非所有选项都相同)。您正在使用 bash 执行此脚本,或者存在关于 declare
的另一条错误消息,或者您已经定义了一些其他命令,包括 declare
,这可能会改变此代码的行为。
None 应该会对您 post 遇到的特定问题产生影响。由 read
创建的变量保持赋值直到子 shell 结束,即直到代码命中 )
,管道的末端(管道的左侧仅在ksh)等
关于 declare
或 typeset
的使用,请注意,您只是将 TOTAL_SIZE
声明为整数。对于其他变量,您只需分配一个恰好仅由数字组成的值。这与您 post 编辑的代码无关,但它可能不是您的意思。
可能发生的一件事是 grep
不匹配任何内容,因此 read
读取空行。您应该检查错误。在脚本中使用 set -e
以在第一个错误时退出。 (有些情况下 set -e
没有捕捉到错误,但这是一个好的开始。)
可能发生的另一件事是 df
将其输出分成多行,因为包含文件系统名称的第一列太大。为防止这种分裂,传递选项 -P
.
使用临时文件是脆弱的:代码可能在只读目录中执行,另一个进程可能想同时访问同一个文件...这里临时文件是没有用的。只需直接通过管道输入 read
。在 ksh 中(与包括 bash 在内的大多数其他 sh 变体不同),管道的右侧在主 shell 中运行,因此对管道右侧变量的赋值在以下命令。
在此特定脚本中无关紧要,但您可以在算术表达式中使用不带 $
的变量。使用 $
替换可能会产生混乱结果的字符串,例如a='1+2'; $((a*3))
扩展为 7
。不使用 $
使用数值(在 ksh 中,a='1+2'; $((a*3))
扩展为 9
;在某些 sh 实现中,您会得到一个错误,因为 a
的值不是数字)。
#!/usr/bin/ksh
set -e
typeset -i TOTAL_SIZE=0 USED_SPACE=0 AVAILABLE_SPACE=0 AVAILABLE_PERCENT=0
df -Pk | grep "rpool/ROOT" | read RPOOL_NAME TOTAL_SIZE USED_SPACE AVAILABLE_SPACE AVAILABLE_PERCENT RSIGN
echo $RPOOL_NAME $TOTAL_SIZE $USED_SPACE $AVAILABLE_SPACE $AVAILABLE_PERCENT $RSIGN
((TOTAL_SIZE=TOTAL_SIZE/1024))