【问题标题】:How to check status of URLs from text file using bash shell script如何使用 bash shell 脚本从文本文件中检查 URL 的状态
【发布时间】:2014-09-27 21:51:18
【问题描述】:

我必须检查 200 个 http URL 的状态并找出其中哪些是损坏的链接。链接存在于一个简单的文本文件中(比如我的 ~ 文件夹中的 URL.txt)。我正在使用 Ubuntu 14.04,我是 Linux 新手。但我知道 bash shell 非常强大,可以帮助我实现我想要的。

我的确切要求是读取包含 URL 列表的文本文件,并自动检查链接是否正常工作,并将响应写入包含 URL 及其相应状态(工作/损坏)的新文件。

【问题讨论】:

  • 如何检查 url 是否有效?通过ping 吗?您能否详细说明您希望使用的方法?否则,在 bash 中读取文件部分非常容易
  • @Ploutox - 我试图寻找无效的网址 - 一个返回 404 错误的网址。使用 curl 解决了这个问题。

标签: linux bash http url ubuntu


【解决方案1】:

如果您的输入文件每行包含一个 url,您可以使用脚本读取每一行,然后尝试 ping url,如果 ping 成功则 url 有效

#!/bin/bash
INPUT="Urls.txt"
OUTPUT="result.txt"
while read line ;
do
  if ping -c 1 $line &> /dev/null
  then
      echo "$line valid" >> $OUTPUT
  else
      echo "$line not valid " >> $OUTPUT
  fi
done < $INPUT
exit

ping 选项:

-c count
      Stop after sending count ECHO_REQUEST packets. With deadline option, ping waits for count ECHO_REPLY packets, until the timeout expires.

您也可以使用此选项来限制等待时间

 -W timeout
      Time to wait for a response, in seconds. The option affects only timeout in absense
      of any responses, otherwise ping waits for two RTTs.

【讨论】:

  • 您可以尝试 ping,但某些防火墙可能会阻止 ICMP 数据包。
【解决方案2】:
#!/bin/bash
while read -ru 4 LINE; do
    read -r REP < <(exec curl -IsS "$LINE" 2>&1)
    echo "$LINE: $REP"
done 4< "$1"

用法:

bash script.sh urls-list.txt

示例:

http://not-exist.com/abc.html
https://kernel.org/nothing.html
http://kernel.org/index.html
https://kernel.org/index.html

输出:

http://not-exist.com/abc.html: curl: (6) Couldn't resolve host 'not-exist.com'
https://kernel.org/nothing.html: HTTP/1.1 404 Not Found
http://kernel.org/index.html: HTTP/1.1 301 Moved Permanently
https://kernel.org/index.html: HTTP/1.1 200 OK

对于所有内容,请阅读Bash Manual。参见man curlhelpman bash

【讨论】:

    【解决方案3】:

    我创建了一个文件“checkurls.sh”并将其放在我的主目录中,其中 urls.txt 文件也位于该目录中。我使用

    授予文件执行权限

    $chmod +x checkurls.sh

    checkurls.sh的内容如下:

    #!/bin/bash
    while read url
    do
        urlstatus=$(curl -o /dev/null --silent --head --write-out '%{http_code}' "$url" )
        echo "$url  $urlstatus" >> urlstatus.txt
    done < $1
    

    最后,我使用以下命令从命令行执行它 -

    $./checkurls.sh urls.txt

    瞧!它有效。

    【讨论】:

    • 太棒了!如果您正在测试重定向,您还可以使用curl -H 'Cache-Control: no-cache' -o /dev/null --silent --head --write-out '%{http_code} %{redirect_url}' 打印目标 URL 并解决大多数 301 问题
    • 不错的解决方案和不错的提示,包括重定向。我在适应的解决方案中添加了一些并行性。太长了,无法发表评论。
    • @brablc - 请用并行度发布您自己的答案。
    • @Enigmativity 它已经在这里了 - 见stackoverflow.com/a/40125113/793937
    【解决方案4】:

    如何为已接受的解决方案添加一些并行性。让我们修改脚本chkurl.sh 使其更易于阅读并且一次只处理一个请求:

    #!/bin/bash
    URL=${1?Pass URL as parameter!}
    curl -o /dev/null --silent --head --write-out "$URL %{http_code} %{redirect_url}\n" "$URL"
    

    现在您使用以下命令检查您的列表:

    cat URL.txt | xargs -P 4 -L1 ./chkurl.sh
    

    这可以将完成工作的速度提高 4 倍。

    【讨论】:

      【解决方案5】:

      这里有我的完整脚本,它检查作为参数传递的文件中列出的 URL,例如'checkurls.sh listofurls.txt'。

      它的作用:

      • 使用 curl 检查 url 并返回 HTTP 状态码
      • 当 url 返回 200 以外的代码时发送电子邮件通知
      • 为失败的 url 创建一个临时锁定文件(文件命名可以改进)
      • 当 url 再次可用时发送电子邮件通知
      • 一旦 url 可用就删除锁定文件以避免进一步的通知
      • 将事件记录到文件并处理增加的日志文件大小(AKA 日志 旋转,如果需要代码 200 日志记录,请取消注释回显)

      代码:

      #!/bin/sh
      
      EMAIL=" your@email.com"
      DATENOW=`date +%Y%m%d-%H%M%S`
      LOG_FILE="checkurls.log"
      c=0
      
      while read url
      do
        ((c++))
        LOCK_FILE="checkurls$c.lock"
        urlstatus=$(/usr/bin/curl -H 'Cache-Control: no-cache' -o /dev/null --silent --head --write-out '%{http_code}' "$url" )
      
        if [ "$urlstatus" = "200" ]
         then
          #echo "$DATENOW OK $urlstatus connection->$url" >> $LOG_FILE
          [ -e $LOCK_FILE ] && /bin/rm -f -- $LOCK_FILE > /dev/null && /bin/mail -s "NOTIFICATION URL OK: $url" $EMAIL <<< 'The URL is back online'
      else
          echo "$DATENOW FAIL $urlstatus connection->$url" >> $LOG_FILE
          if [ -e $LOCK_FILE ]
           then
              #no action - awaiting URL to be fixed
              :
          else
              /bin/mail -s "NOTIFICATION URL DOWN: $url" $EMAIL <<< 'Failed to reach or URL problem'
              /bin/touch $LOCK_FILE
          fi
        fi
      done < $1
      
      # REMOVE LOG FILE IF LARGER THAN 100MB
      # alow up to 2000 lines average
      maxsize=120000
      size=$(/usr/bin/du -k "$LOG_FILE" | /bin/cut -f 1)
      if [ $size -ge $maxsize ]; then
           /bin/rm -f -- $LOG_FILE > /dev/null
           echo "$DATENOW LOG file [$LOG_FILE] has been recreated" > $LOG_FILE
      else
           #do nothing
           :
      fi
      

      请注意,更改文本文件中列出的 url 的顺序将影响任何现有的锁定文件(删除所有 .lock 文件以避免混淆)。可以通过使用 url 作为文件名来改进它,但使用某些字符,例如:@/? & 必须针对操作系统进行处理。

      【讨论】:

        【解决方案6】:

        我最近发布了deadlink,这是一个用于查找文件中损坏链接的命令行工具。安装

        pip install deadlink
        

        并用作

        deadlink check /path/to/file/or/directory
        

        deadlink replace-redirects /path/to/file/or/directory
        

        后者将替换指定文件中的永久重定向(301)。

        示例输出:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-13
          • 2013-01-05
          • 2012-01-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多