繁体   English   中英

在 Bash Shell 脚本中检查常规文件和目录所有权以及组成员身份

[英]Checking Regular File and Directory Ownership and Group Membership in a Bash Shell Script

我正在 Solaris 10 下的 Bash 3.2.57(1)-release 中编写 shell 脚本(uname -a 产生“SunOS 主机名 5.10 Generic_150400-35 sun4v sparc sun4v”)。

我试图解决的最终问题是,在 bash shell 脚本中,确定常规文件或目录的所有者和组成员身份。

不幸的是,我无法使用 stat。

由于 stat 不可用,我所知道的下一个最好的事情是从 ls -l 的输出中解析所有者和组成员身份。 我不喜欢这种方法,以防可移植性成为一个问题,以防我遇到带有特殊字符的文件名,从而导致解析失败。 但是,解析 ls -l 的输出是我目前所得到的......

这导致两个问题。

问题一

没有 stat并且排除 ls -l作为解决方案的一部分的条件下,是否有一种可接受的,不太黑客的方式来确定我的特定平台上的常规文件或目录的所有者和组成员身份(Bash 3.2.57(1)-在 Solaris 10 下发布)?

在谷歌搜索中,这似乎是一个真正的挑战。

如果有人对解析 ls 的替代方法有任何建议,我肯定会很高兴听到他们的建议。

问题二

这是我目前通过解析 ls -l 输出的最佳尝试:

#!/usr/bin/bash

###
###
###
# This functions returns success if:
# 1. The ownership of the pass file is root AND
# 2. The group membership of the passed file is root
#
# This function returns failure otherwise.
function check_if_ownership_and_group_membership_are_root
{
   if [[ $# -ne 1 ]]; then
      echo
      echo "Usage: ${FUNCNAME[0]} <filename>"
      echo "Actual (incorrect) usage: ${FUNCNAME[0]} $*"
      echo "ABORTING SCRIPT; Failure point is designated \"Point 1\""

      exit 1
   fi

   local FILENAME="${1}"

   # Check ownership of "${FILENAME}".
   if [[ $(ls -l "${FILENAME}" | awk '{print $3}')="root" ]]; then
      echo
      echo "Part 1: Test of ownership being root supposedly passed"
      echo "Actual ownership: " $(ls -l "${FILENAME}" | awk '{print $3}')

      # The test of ownership being root passed. Continue on to test the group membership being root.
   else
      echo
      echo "Part 2: Test of ownership being root supposedly failed"
      echo "Actual ownership: " $(ls -l "${FILENAME}" | awk '{print $3}')

      # The test of ownership being root did not pass. Return failure.
      return 1
   fi

   # Check the group membership of "${FILENAME}".
   if [[ $(ls -l "${FILENAME}" | awk '{print $4}')="root" ]]; then
      echo
      echo "Part 1: Test of group membership being root supposedly passed"
      echo "Actual group membership: " $(ls -l "${FILENAME}" | awk '{print $4}')

      # The ownership test previously passed, and now the group membership test passed.
      # Return success.
      return 0
   else
      echo
      echo "Part 2: Test of group membership being root supposedly failed"
      echo "Actual group membership: " $(ls -l "${FILENAME}" | awk '{print $4}')

      # The test of group membership being root did not pass. Return failure.
      return 1
   fi

   # Should never be able to get here. Abort the script.
   echo
   echo "ABORTING SCRIPT; Failure point is designated \"Point 2\""
   exit 1
}

# Show what ls is being invoked.
echo "Here is what ls will be used:"
type ls

# For this example, I'll just use ad hoc file test.txt to demonstrate the problem I'm having.
FILENAME=./test.txt
touch "${FILENAME}"

###
###
###
# Test the success case of the file ownership being root and the file group membership being root.
chown root "${FILENAME}"
chgrp root "${FILENAME}"

# Display the actual file ownership and group membership.
echo
echo "Test of success case starting; here's the file being tested:"
ls -l "${FILENAME}"

# Perform the check of ownership being "root" and group membership being "root".
if check_if_ownership_and_group_membership_are_root "${FILENAME}"; then
   echo
   echo "FINAL RESULT: SUCCESS"
else
   echo
   echo "FINAL RESULT: FAILURE"
fi

###
###
###
# Test the failure case of the file ownership not being root or the file group membership not being root.
chown nobody "${FILENAME}"
chgrp other "${FILENAME}"

# Display the actual file ownership and group membership.
echo
echo "Test of failure case starting; here's the file being tested:"
ls -l "${FILENAME}"

# Perform the check of ownership being "root" and group membership being "root".
if check_if_ownership_and_group_membership_are_root "${FILENAME}"; then
   echo
   echo "FINAL RESULT: SUCCESS"
else
   echo
   echo "FINAL RESULT: FAILURE"
fi

这导致以下输出:

bash-3.2# ./script.sh
Here is what ls will be used:
ls is /usr/bin/ls

Test of success case starting; here's the file being tested:
-rw-------   1 root     root          16 Aug 25 13:34 ./test.txt

Part 1: Test of ownership being root supposedly passed
Actual ownership:  root

Part 1: Test of group membership being root supposedly passed
Actual group membership:  root

FINAL RESULT: SUCCESS

Test of failure case starting; here's the file being tested:
-rw-------   1 nobody   other         16 Aug 25 13:34 ./test.txt

Part 1: Test of ownership being root supposedly passed
Actual ownership:  nobody

Part 1: Test of group membership being root supposedly passed
Actual group membership:  other

FINAL RESULT: SUCCESS

可以看出,我使用“if”语句测试的条件总是通过。 我究竟做错了什么?

(尽管我希望有人能指导我不要解析 ls,但为了教育起见,无论如何我仍然想知道这个问题的答案。)

提前感谢所有响应者。

比较运算符=周围需要空格:

[[ $(ls -l "${FILENAME}" | awk '{print $4}') = "root" ]]

此外,当您使用双括号[[ ... ]]编写条件时,您应该使用==而不是=

一般不推荐依赖ls的输出

if ! [[ $(stat --format '%G' "${FILENAME}") = "root" ]]; then
    echo "do the thing"
fi

Shellcheck wiki 讨论了依赖 ls 输出的一些陷阱: https : //github.com/koalaman/shellcheck/wiki/SC2012

引用:

ls仅供人类使用:它具有松散的非标准格式,并且可以“清理”文件名以使输出更易于阅读。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM