web-dev-qa-db-ja.com

Wget segfault ---これを引き起こしているサイトを知るにはどうすればよいですか?

ローカルでウェブサイトをミラーリングしようとしています。ただし、ダウンロードの一貫した時点で、ターゲットとしているサイトとは異なるドメインでセグメンテーション違反が発生しています(おそらく--page-requisitesが原因です)。

2018-04-09 04:58:32 (346 KB/s) - './not-website.com/2017/06/28/xyz/index.html' saved [145810]

29247 Segmentation Fault      (core dumped) wget --directory-prefix="${DL_ROOT}" --recursive --page-requisites --span-hosts --tries="${TRIES_NUM}" --timeout="${TIMEOUT_NUM}" --reject="*.tar" --convert-links --adjust-extension --continue --no-check-certificate "http://website.com/"

その結果、セグメンテーション違反は、wgetが特定のWebサイトをダウンロードしようとしたが、失敗したことが原因であると考えられます。

ただし、エラーメッセージは、wgetが失敗しているアドレスを教えてくれないようです。最後に成功したダウンロードのみを通知します。 このセグメンテーション違反でwgetが失敗する場所/理由をどのように把握できますか?

エラーが(core dumped)で参照しているように見える55Mのcoreファイルがありますが、プレーンテキストではありません。そこに必要な情報はありますか?それをどのように抽出しますか?

私はこれをディストリビューション(Solaris、Debian、Raspbian)でテストしましたが、このセグメンテーション違反は一貫しており、常に同じアドレス(上記のエラーメッセージのnot-website.com/...)の後にあります。

私は次のコマンドを使用しています:

$ wget \
    --directory-prefix="${DL_ROOT}" \
    --recursive \
    --page-requisites \
    --span-hosts \
    --tries="${TRIES_NUM}" \
    --timeout="${TIMEOUT_NUM}" \
    --reject="*.tar" \
    --convert-links \
    --adjust-extension \
    --continue \
    --no-check-certificate \
  "http://website.com/"

追加情報

かなりのメディアがある大きなサイトです。障害点では、ダウンロードされたディレクトリサイズは約252Mです。

テスト済み:

GNU Wget 1.18 built on solaris2.10.

-cares +digest -gpgme +https +ipv6 -iri +large-file -metalink -nls 
+ntlm +opie -psl +ssl/openssl 

そして

GNU Wget 1.18 built on linux-gnu.

-cares +digest -gpgme +https +ipv6 +iri +large-file -metalink +nls 
+ntlm +opie +psl +ssl/gnutls

そして

GNU Wget 1.16 built on linux-gnueabihf.

+digest +https +ipv6 +iri +large-file +nls +ntlm +opie +psl +ssl/gnutls
3
ning

セグメンテーション違反とは、プログラム(この場合はwget)が無効なメモリアドレスにアクセスしようとしたため、カーネルによって終了されたことを意味します。これは通常、プログラムのバグが原因で発生するため、特定のWebサイトまたはWebページによってトリガーされている可能性が非常に高いです(複数のプラットフォームで、同じ時点で、非常に一貫してそれを再現できると思われる場合)。まだwget自体のバグを公開している可能性があります。

Wgetのどこでセグメンテーション違反が発生しているかを見つけるために、gdbプログラム(GNUデバッガー)を使用して、クラッシュしたときのwgetのスタックトレースを取得できます。これは、coreファイルがあるため可能です。 (コアダンプは、セグメンテーションフォールトなどの無効な操作が原因で終了した時点で実行中のプログラムのイメージのコピーです。)

そのためには、次のコマンドを使用します。

$ gdb wget core

(パスから)wgetバイナリでデバッガーを開始し、(現在のディレクトリにある)coreファイルを実行中のプログラムのイメージとして復元します。

gdbは、プログラムに関する情報を出力し、プロンプトを表示します。

$ gdb wget core
GNU gdb (GDB) 7.9
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
...
Core was generated by `wget --directory-prefix=... --recursive --page-requisites --span-hosts --tries=... --timeout=... --reject=*.tar --convert-links --adjust-extension --continue --no-check-certificate http://website.com/'.
Program terminated with signal SIGSEGV, Segmentation Fault.
(gdb) _

この時点で、コマンドbt(「backtrace」の略)を使用して、プログラムがクラッシュしたときに実行されていた内容を表示できます。これは通常、バグの検索を開始するのに適した場所です。

たとえば、次のようなものが表示される場合があります。

(gdb) bt
#0  0x00007f5371206363 in __select_nocancel () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x0000559e5acbf21c in select_fd ()
#2  0x0000559e5acf0bde in wgnutls_poll ()
#3  0x0000559e5acbf3a2 in poll_internal ()
#4  0x0000559e5acbf6ed in fd_peek ()
#5  0x0000559e5ace423d in fd_read_hunk ()
#6  0x0000559e5acd5ef9 in gethttp ()
#7  0x0000559e5acd9b26 in http_loop ()
#8  0x0000559e5ace53c8 in retrieve_url ()
#9  0x0000559e5ace273b in retrieve_tree ()
#10 0x0000559e5acbe67d in main ()

次に、gdb(「quit」の場合)コマンドを使用してqを終了できます。

(gdb) q

通常、「デバッグシンボル」がインストールされていると便利です。これらは、バイナリをデバッグするためにコンパイラによって生成される情報であり、通常、システムにインストールされているバイナリでは削除されるため、サイズが小さくなります。その情報は、バイナリをデバッグするときにgdbによって検索できる別の場所(通常は/usr/lib/debugの下)に保存できます。

その情報が存在する場合、バックトレースには通常、すべての内部関数の名前など、より多くの情報が付加されます。

Debianでは、次のコマンドを使用してwgetのデバッグ情報をインストールできます。

$ Sudo apt-get install wget-dbgsym

Glibcのデバッグシンボルをインストールすることもできます。

$ Sudo apt-get install libc6-AMD64-dbgsym

そうは言っても、wgetがクラッシュした理由を調べる前に、最新バージョンのwgetを試してみてください。ダウンロードできるのはバージョン1.9.4です こちら 。これはソースパッケージであるため、システムで機能させるには、ソースからビルドする必要がある場合があります。

これは、セグメンテーション違反は通常バグが原因で発生するためです。このバグはwgetですでに修正されており、最新バージョンで修正されている可能性があります。

最新バージョンで同じ問題が発生する場合は、コアファイルを取得し、gdbを使用してバックトレースを取得してから、バグをwgetのメンテナーに報告して、メンテナーが対処できるようにします。

最新のwget 1.9.4で修正されているが、使用しているDebianのバージョンに存在する場合は、Debianに報告することを検討してください。そうすれば、パッチをwgetのバージョンにバックポートできるようになります。

wget2 という新しいプロジェクトもあります。彼らはwgetを新しいコードベースに置き換えようとしているようです。これが機能するかどうかを確認したいかもしれません...最近のDebianでは「wget2」という名前で出荷されているようです。

これらのポインタもお役に立てば幸いです。

1
filbranden