网站调试
我知道,我现在正在写一系列关于如何在命令行中使用 ImageMagick 的专栏文章,但是当其他事情出现时,嗯,我想你们很多人都以某种方式参与服务器或系统的管理,所以你们都理解救火。
当然,这意味着你们也都理解负反馈循环,它是系统管理和 IT 管理的内在组成部分。我的意思是,人们不会打电话给你,CEO 也不会发备忘录说:“系统整天运行良好,打印机甚至也打印了。谢谢!”
不,只有当事情出错时你才会听到消息,而这种忽视好的方面,不得不处理坏的方面(当它出现时)的倾向,不仅是企业 IT 的一个特点,如果你运行自己的系统,这也是同样真实的——这就是这个月它突然出现并困扰我的方式。
这一切都始于十年前我的 Ask Dave Taylor 网站。你可能已经遇到过它,因为它已经存在十多年了,并且在此期间为数千万访客提供了有用的教程信息。
十年前,选择 Movable Type 作为我的博客平台是完全合理的,并且是原始的、未完成的 WordPress 平台及其永无止境的黑客和问题的明智替代方案。然而,正如每个企业 IT 人员都知道的那样,有时你会锁定错误的平台,然后被困住,迁移所需的工作量每月都在增加,但什么都没有发生。
因此,为了网站的十周年纪念,是时候了。我不得不咬紧牙关,将所有 3,800 篇文章和 56,000 条评论从 Movable Type 迁移到 WordPress,因为是的,WordPress 赢了,并且显然是当今内容管理系统的行业标准。
这项任务令人生畏,不仅仅是因为导入的规模(它需要咨询团队重写标准导入工具以处理如此多的文章和评论),还因为命名方案发生了变化。在 Movable Type 上,我总是将其设置为将文章的名称转换为像这样的 URL
名称:Pinterest 入门
URL:/getting_started_with_pinterest.html
这很简单直接,但是在 WordPress 上,URL 使用破折号而不是下划线,更重要的是,它们不以 .html 结尾,因为它们是根据需要动态生成的。这意味着新的 WordPress 站点的默认 URL 看起来像这样
新 URL:/getting-started-with-pinterest/
URL 可以在导入时进行映射,以便默认的破折号变为下划线,但后缀是一个问题,并且在导入后,有 3,800 个 URL 损坏了,因为每个指向 xx_xx.html 的链接都失败了。
啊! 301 重定向! 是的,但是数千个重定向会减慢每个人的服务器速度,因此重写规则更好。在 Apache 中,你可以指定“如果你看到 xx_xx.html 形式的 URL,将其重写为 'xx_xx' 并重试”,这是一个非常方便的功能。
但是生活从来没有那么容易,因为虽然这种重写适用于旧站点上 95% 的 URL,但有些 URL 最终会得到不同的 URL,因为我在某个地方修改了一些东西。是的,总会有一些事情。
例如,旧站点 URL /schedule_facebook_photo_upload_fan_page.html 现在在服务器上的 URL 是 /schedule-a-facebook-photo-upload-to-my-fan-page/。
这很有帮助,对吧?(叹气。)
这些都可以通过 301 重定向来处理,但问题是,在旧站点上近 4,000 个文章 URL 中,哪些实际上没有成功地通过重写规则(.html 到尾部斜杠)映射到新服务器上的页面?
终于要写脚本了为了识别这些重写失败,我必须创建一个脚本——而且要快。毕竟,虽然内部链接可能仍然有效,但来自 Popular Science、华尔街日报、Wired 和其他地方的数千个外部链接已损坏。哎呀——一点也不好。
我从命令行开始,使用一个我知道会失败的链接。这是当我使用 curl 获取新站点上的错误 URL 时发生的情况
$ curl
http://www.askdavetaylor.com/
↪schedule-facebook-photo-upload-to-my-fan-page.html
| head -5
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:--
0<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8" />
<h3>Nothing found for
Schedule-A-Facebook-Photo-Upload-To-My-Fan-Page</h3>
100 31806 0 31806 0 0 110k 0 --:--:-- --:--:-- --:--:-- 110k
curl: (23) Failed writing body (0 != 754)
哎呀,这真是太乱了,这并不奇怪,因为我忘记在调用 curl
时添加 -silent
标志。
尽管如此,这里显示的内容足以提供一个重要的线索。这是一个 404 错误页面,正如预期的那样,<h3> 表明了这一点
<h3>Nothing found for ...
所以这是一个容易搜索的模式
curl -silent URL | grep '<h3>Nothing found for'
这招奏效了。如果输出是非零的,则链接失败并生成了 404 错误,但如果链接有效,它将是文章的正确标题,并且会出现“Nothing found for”字样。
这已经是脚本所需的大部分逻辑了。唯一剩下的步骤是模拟重写规则,以便所有有效的链接都不会被标记为问题。很简单
newname="$(echo $name | sed 's/\.html/\//')"
实际上,这是一个我在脚本中使用的超级常见的序列,使用子 shell 调用 $( )
回显变量的当前值,只是为了将其通过 sed
替换,在本例中将 .html 替换为尾部斜杠(需要用前导反斜杠转义,因此模式很复杂)。
将其包装在一个 for 循环中,该循环遍历所有可能的 *.html 文件,这就是它的样子
for name in *.html ; do
newname="$(echo $name | sed 's/\.html/\//')"
test=$($curl $base/$newname | grep "$pattern")
if [ -n "$test" ]
then
echo "* URL $base/$name fails to resolve."
fi
done
但这很无聊,因为当我在做这件事的时候,我想知道测试了多少个 URL 以及遇到了多少个错误。我的意思是,为什么不呢,对吧?量化 = 好。
事实证明,这很容易添加,只需添加两个新变量(这两个变量都需要在脚本顶部设置为零)
for name in *.html ; do
newname="$(echo $name | sed 's/\.html/\//')"
test=$($curl $base/$newname | grep "$pattern")
if [ -n "$test" ] ; then
echo "* URL $base/$name fails to resolve."
error=$(( $error + 1 ))
fi
count=$(( $count + 1 ))
done
然后在脚本的最后,在报告所有特定错误之后,进行状态更新
echo ""; echo "Checked $count links, found $error problems."
太棒了。让我们运行它
$ bad-links.sh | tail -5
* URL http://www.askdavetaylor.com/whats_a_fast_way_to_add_a_
↪store_and_shopping_cart_to_my_site.html fails to resolve.
* URL http://www.askdavetaylor.com/whats_amazons_simple_
↪storage_solution_s3.html fails to resolve.
* URL http://www.askdavetaylor.com/whats_my_yahoo_
↪account_password_1.html fails to resolve.
* URL http://www.askdavetaylor.com/youtube_video_
↪missing_hd_resolution.html fails to resolve.
Checked 3658 links, found 98 problems.
呼。现在我知道了特殊情况,可以应用自定义 301 重定向来修复它们。当你读到这篇文章时,网站上一切都会好起来的(或者应该会更好)。