避免 UNIX 和 Linux 中的常见错误

了解 UNIX® 和 Linux® 中最常见的错误以及如何避免它们。

Adam Cormany, 国家数据中心经理, IBM

Adam Cormany 是一位 UNIX 系统工程师,从事 AIX、Solari 和 Red Hat Linux 管理已有 10 多年。他是一位 pSeries® AIX 系统管理方面的 IBM eServer® 认证专家。除管理外,Adam 还在 BASH、CSH 和 KSH 的 Shell 脚本编写以及 C、PHP 和 Perl 编程方面具有渊博的知识。



2009 年 8 月 27 日

您是否遇到过 Execute permission deniedThe parameter list is too long 这样的错误消息?您想知道错误的原因吗?这些是 UNIX 和 Linux 新手经常遇到的错误,他们可能不知道如何避免这些问题。本文解释这些错误并提供解决方法。

./foo: 0403-006 Execute permission denied.

您编写或下载了一个新的 shell 脚本,很想试试它。这听起来不错,但是在试图执行这个命令时,收到了错误消息 ./foo: 0403-006 Execute permission denied。怎么回事儿?这个消息可能源于两个问题:

  • 您不具有执行这个命令的足够权限。
  • 对于脚本中定义的 shell,您不具有足够的权限,无法告诉 shell 应该如何解释脚本和其中的命令。

您不具有执行这个命令的足够权限

检查权限最简便的方法是,查看您是作为哪个用户登录服务器的,然后查看 ls –l 的输出:

# id
uid=5008(cormany) gid=330(atc) groups=110(sales),201(sshd)

# ls -l foo
-rwxrw-r--    1 cormany  atc              75 Jun 10 18:46 foo

根据这个示例,您是作为用户 cormany 登录的,而 shell 脚本的所有者是 cormany,他具有 rwx 权限(即读、写和执行)。这没问题,所以我们考虑下一个可能的原因。

对于脚本中定义的 shell,您不具有足够的权限,无法告诉 shell 应该如何解释脚本和其中的命令

我们来看看脚本的内部:

# cat foo

#!/bin/ksh.new

echo "This is a just a test"

exit 0

根据第一行,这个脚本看起来应该作为 Korn shell 脚本进行解释。通过检查所用的 shell 的权限,可以确认实际上是否可以使用它:

# ls –l /bin/ksh.new

-r-xr-x---    5 bin      bin          289072 May 27 19:03 /bin/ksh.new

作为 root 用户,修改要使用的 shell 的文件权限,然后再试一次:

  1. 切换为 root 用户:
    # su -
    root's Password:
  2. 确认您现在是 root 用户而不是原来的用户:
    # id
    uid=0(root) gid=0(system) groups=2(bin),3(sys),7(security),8(cron),10(audit),11(lp)
  3. 修改文件的权限:
    # chmod 555 /bin/ksh.new
  4. 确认文件权限已经改变了:
    # ls -l /bin/ksh.new
    -r-xr-xr-x    1 bin      bin          289072 Jun 10 18:45 /bin/ksh.new
  5. 退出 su,恢复为原来的用户:
    # exit
    # id
    uid=5008(cormany) gid=330(atc) groups=110(sales),201(sshd)
  6. 再次尝试执行脚本:
    # ./foo
    This is a just a test

好了,问题解决了!


ksh: bar: not found.

您编写了另一个脚本 bar 并把它保存在 ~cormany/scripts 目录中。在使用完整路径或在当前工作目录 (~cormany/scripts) 中执行这个脚本时,它工作正常;但是,由于某种原因,如果在另一个目录中只输入脚本名,就无法运行它:

# pwd
/home/cormany/scripts

# /home/cormany/scripts/bar
This is another test

# ./bar
This is another test

# cd

# pwd
/home/cormany

# barksh: bar:  not found.

一切正常,只是无法从另一个目录运行这个脚本。这样的错误消息通常有三种情况:

  • 对于试图执行的文件,您没有权限。
  • 文件不存在或不在您认为的目录中。
  • 文件存在而且在预期的位置,您对这个文件也有足够的权限。

对于试图执行的文件,您没有权限

您知道不是这个原因,因为在提供完全限定的路径时或在命令目录中时能够执行这个脚本。如果不能排除这种可能性,检查文件权限应该有助于发现问题的原因:

# ls -la ~cormany/scripts
total 56
drwxr-xr-x    2 cormany  atc             512 Jun 12 08:30 .
drwxr-xr-x    6 cormany  atc             512 Jun 10 08:21 ..
-rwxr-xr-x    1 cormany  atc              42 Sep 06 16:20 amdc
-rw-rw-rw-    1 cormany  atc             154 Jan 27 23:23 atc
-rwxr-xr-x    1 cormany  atc             206 Aug 04 20:57 atc.2
-rwxr-xr-x    1 cormany  atc              48 Jun 12 08:21 bar
-rwxr-xr-x    1 cormany  atc              87 Feb 22 16:11 pac

执行 ~cormany/scripts/atc 命令会失败,因为这个文件只对用户、组和其他用户设置了读和写权限。只需增加执行权限,即可解决这个问题。

如果无法执行另一个目录中的另一个命令(例如 ~cormany/scripts.old/cujo),那么也应该检查那个文件的权限:

# ls -l ~cormany/other_scripts/cujo
ls: 0653-345 /home/cormany/other_scripts/cujo: Permission denied.

初看上去,您甚至没有读权限。我们来看看目标目录,看看是怎么回事儿:

# cd ~cormany/scripts.old/cujo
ksh: /home/cormany/other_scripts: Permission denied.

# ls -l ~cormany/scripts.old/cujo
ls: /home/cormany/scripts.old: The file access permissions do 
    not allow the specified action.
total 0

这里发生了什么情况?这是另一种形式的权限错误。权限错误不总是出现在文件本身,也可能出现在文件路径中的目录上:

# ls -ld ~cormany/scripts.old
d---------    2 cormany  atc             512 Jan 22 08:42 /home/cormany/scripts.old

如果文件本身有足够的权限,那么纠正目录路径上的权限应该会解决执行问题:

# chmod 755 ~cormany/other_scripts
# cd ~cormany/other_scripts
# ls –l cujo
-rwxr-xr-x    1 cormany  atc              48 Jan 26 08:21 cujo

现在,回到原来 ~cormany/scripts/bar 的问题。

文件不存在或不在您认为的目录中

同样,使用 ls 命令执行快速检查,应该会看到这个文件是否存在:

# ls -l ~cormany/scripts/bar
-rwxr-xr-x    1 cormany  atc              48 Oct 05 08:21 /home/cormany/scripts/bar

如果在您原来认为的目录中没有这个文件,就会收到以下消息:

# ls -l ~cormany/scripts/bar
ls: 0653-341 The file /home/cormany/scripts/bar does not exist.

如果您认为这个文件在用户 cormany 的主目录中的其他地方,可以用 find 命令搜索它(如果您有足够的权限的话):

# find ~cormany -name "bar" -ls
16409    1 -rwxr-xr-x  1 cormany   atc   48 Sep 06 08:06 /home/cormany/atc/bar
590040   1 -rwxr-xr-x  1 cormany   atc   48 Sep 09 08:42 /home/cormany/test/bar

文件存在而且在预期的位置,您对这个文件也有足够的权限

前面成功执行时采用的方法是提供完全限定的命令路径,或者处于命令目录中并输入当前工作目录(即使用 ./)。既然现在不在命令目录中,也不输入完整路径,我们就来检查一下 PATH 环境变量的值:

# echo ${PATH}
/usr/bin:/etc:/usr/sbin:/usr/ucb:/bin:/usr/bin/X11:/sbin:/usr/
    java5/jre/bin:/usr/java5/bin:/usr/ushare/bin:/usr/local/bin

目录 /home/cormany/scripts 不在路径中。纠正这个问题有两种方法:

  • 在 PATH 中添加 ~cormany/scripts尽管很容易执行这个修改,但是请记住一点:每在 PATH 变量中添加一个目录,shell 在搜索命令时就会多搜索一个目录。如果随着时间的推移添加了 10 个目录,那么在 shell 返回无法找到文件的结果之前,它要多搜索 10 个目录。如果您确实要这么做,只需执行以下命令:
    # export PATH=${PATH}:/home/cormany/scripts
    # echo $PATH
    /usr/bin:/etc:/usr/sbin:/usr/ucb:/bin:/usr/bin/X11:/sbin:/usr/
        java5/jre/bin:/usr/java5/bin:/usr/ushare/bin:/usr/local/bin:/
        home/cormany/scripts

    注意:把路径添加到用户的 PATH 变量的开头通常是不明智。这么做可能导致执行不需要的命令。如果您觉得必须把一个路径放在开头,一定要谨慎。

  • 把脚本转移(或复制)到 PATH 变量中已有的目录中。如果多个用户可能使用这个脚本,这种解决方案比较好。如果是这种情况,用户通常把他们的文件放在 /usr/local/bin 中。

ls: 0653-341 The file . does not exist.

您正在 ~cormany/scripts 目录中工作。突然,这个目录中的脚本都找不到了,您收到一条奇怪的消息,它说当前工作目录不再存在:

#  ls -l
total 40
-rwxr-xr-x    1 cormany  atc              42 Sep 06 16:20 amdc
-rw-rw-rw-    1 cormany  atc             154 Jan 27 23:23 atc
-rwxr-xr-x    1 cormany  atc             206 Aug 04 20:57 atc.2
-rwxr-xr-x    1 cormany  atc              48 Jun 12 08:21 bar
-rwxr-xr-x    1 cormany  atc              87 Feb 22 16:11 pac

# ./bar
This is another test

# pwd
/home/cormany/scripts

# ./barksh: ./bar:  not found.

# ls -lls: 0653-341 The file . does not exist.

当出现这种情况时,就说明通过 rm 命令删除了您原来的工作目录。仅仅创建一个同名的新目录不会解决这个问题,因为文件描述符不一样。

出现这种事故常常是因为您自己在另一个窗口中执行了 rm 命令(至少我是这样)。为了避免这种事故,可以通过 mv 命令修改目录名。如果修改目录名,原来目录中的用户可以继续工作,只是采用不同的目录名,因为文件描述符仍然是相同的:

#  ls -l
total 40
-rwxr-xr-x    1 cormany  atc              42 Sep 06 16:20 amdc
-rw-rw-rw-    1 cormany  atc             154 Jan 27 23:23 atc
-rwxr-xr-x    1 cormany  atc             206 Aug 04 20:57 atc.2
-rwxr-xr-x    1 cormany  atc              48 Jun 12 08:21 bar
-rwxr-xr-x    1 cormany  atc              87 Feb 22 16:11 pac

# ./bar
This is another test

# pwd
/home/cormany/scripts

同样,假设有人在另一个会话中把您正在工作的目录改为 ~cormany/scripts.20090601。由于只是转移目录和修改目录名,您仍然可以继续工作:

# ./bar
This is another test

# pwd
/home/cormany/scripts.20090601

./foo: /usr/bin/ls: 0403-027 The parameter list is too long.

一个程序在您的 IBM® AIX® 计算机上已经运行了几个月,没有出现问题。但是,在这个程序运行时,它每隔几分钟在同一个日志目录中创建文件。文件名以 f.<number>e.<number> 开头。目录越来越满,ls 命令的响应时间显著增加。这是可以理解的,因为目录中的文件太多了。

又过了几个月,这个 AIX 程序一直运行,仍然没有问题。现在,有了 100,000 个以 f. 开头的文件和另外 100,000 个以 e. 开头的文件。现在,如果您试图清理这个日志目录,删除以 f. 开头的文件,就会收到以下消息:

# rm ~cormany/logs/f.*
ksh: /usr/bin/rm: 0403-027 The parameter list is too long.

我认为您太久没有清理文件了。但是,现在还不晚。

在执行 delete 等命令时,会在执行之前检查和展开所有参数。这个示例寻找 ~cormany/logs/f.*,这会展开为 rm 命令的 100,000 个参数。换句话说,实际上执行的并不是 rm ~cormany/logs/f.*,而是 rm ~cormany/logs/f.1 ~cormany/logs/f.2 ~cormany/logs/f.3 … ~cormany/logs/f.100000

与其他 UNIX 和 Linux 操作系统一样,AIX 规定了可以使用的命令行参数和环境变量的长度。在 AIX 中,可以使用 getconf 命令检查这个值。在 getconf 手册页上,应该会看到 ARG_MAX

# man getconf
…
  ARG_MAX
    Maximum length, in bytes, of the arguments for one of the exec 
    subroutines, including environment data.
…
# getconf ARG_MAX
1048576

这个值说明对于环境变量和命令行参数可以使用 1,048,576 字节。看起来您已经超过了这个上限。解决这个问题有两种方法:

  • 使用 smitty chgsys 并修改 ARG/ENV list size in 4K byte blocks 以提高这个值,或者使用 chdev 提高这个值。我不建议在每次遇到这类错误时为了图方便修改系统范围的参数:这应该是最后一招。
  • 不使用带 100,000 个参数的 rm 命令(这会执行失败),而是使用 find 命令删除文件,这会好得多:
    # find ~cormany/logs –name “f.*” –exec rm {} \;

    find 命令在目录中搜索以 f. 开头的所有文件,而不是在 shell 命令行中放那么多参数。然后,find 命令对找到的每个文件执行 rm,这样就会删除以 f. 开头的所有文件。


结束语

读完本文之后,您应该了解了这些常见问题,知道如何快速地解决问题。错误可能看起来很简单,但是在 UNIX 中您必须解决基本错误,才能顺利地前进。愿您能够顺利地排除故障!

参考资料

学习

  • getconf:阅读 IBM 的 getconf 命令手册页。
  • AIX and UNIX 专区:developerWorks 的“AIX and UNIX 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 UNIX 技能。
  • AIX and UNIX 新手入门:访问“AIX and UNIX 新手入门”页面可了解更多关于 AIX 和 UNIX 的内容。
  • AIX and UNIX 专题汇总:AIX and UNIX 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。
  • 技术书店 浏览关于这些主题和其他技术主题的图书。
  • developerWorks 技术活动网络广播:随时关注 developerWorks 技术活动和网络广播。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=AIX and UNIX, Linux
ArticleID=423303
ArticleTitle=避免 UNIX 和 Linux 中的常见错误
publish-date=08272009