yum Tips
決してタイトル考えるのが面倒くさいとかそんなことはないです。信じてください。
久々にyum updateするとエラーで更新できなくなってました。
yumはネットワーク絡みでエラーになることが非常に多いので、
備忘録として詰まった部分はここに書いていこうと思います。例によって適宜更新します。
私の環境はCentOS6.6(Final)です。
CentOS7以降の環境については後々気が向けば追記して行こうと思います。
基本中の基本。クライアント側のネットワークの設定。
ゲートウェイの設定(デフォルトゲートウェイ)の設定
netstat -rn
もしくは
route
でデフォルトゲートウェイが設定されているか確認してください。
ダメな例。ゲートウェイが設定されていません。
Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
/etc/yum.repos.d/network.confに以下を追記してください。
デフォルトゲートウェイのアドレスはご自身の環境に合わせてくださいね。
GATEWAY=192.168.1.1
ネットワークサービスを再起動します。
service network restart
デフォルトゲートウェイ(0.0.0.0)が追加されました。これでOK。
Destination Gateway Genmask Flags MSS Window irtt Iface 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth1
ネームサーバー(DNSサーバー)の設定
DHCPの場合は自動で設定されているかもしれません。
/etc/resolv.confにnameserverのエントリがない場合は追記してください。
自分の場合は自動で入っていました。(以下例です)
; generated by /sbin/dhclient-script nameserver 192.168.1.1
エラーが起こっているyumリポジトリを無効にする
自分はDVDをyumのリポジトリに設定しているのですが、うっかりマウントし忘れていたりすると
エラーが発生し以降の処理が打ち切られてしまっていました。(以下はエラーの例です)
エラーが発生しているyumリポジトリのファイルを開いてenable=0としておきましょう。
[root@hogehoge ~]# yum update 読み込んだプラグイン:fastestmirror 更新処理の設定をしています Determining fastest mirrors : base | 3.7 kB 00:00 base/primary_db | 4.6 MB 00:01 file:///mnt/media/repodata/repomd.xml: [Errno 14] Could not open/read file:///mnt/media/repodata/repomd.xml 他のミラーを試します。 エラー: Cannot retrieve repository metadata (repomd.xml) for repository: centos-media. Please verify its path and try again
プロキシの下にいる場合
プロキシサーバーのアドレスと認証があればIDとパスワードが必要です。
/etc/yum.confに以下を記載してください。
proxy=http://proxy.net:8080 proxy_username=user1 proxy_password=user1foo
ミラーリストやパッケージ等の接続先サーバーの設定
長い間放置しているとエラーになることがあります。
例えば自分の場合/etc/redhat-releaseをみると6.6 (Final)なので、
/etc/yum.repos.d/CentOS-Base.repoの[base]のmirrorlistは
http://mirrorlist.centos.org/?release=6.6&arch=x86_64&repo=os&infra=stock
となります。実際ブラウザなどで見に行くと・・・
http://mirror.fairway.ne.jp/centos/6.6/os/x86_64/ http://ftp.riken.jp/Linux/centos/6.6/os/x86_64/ http://ftp.tsukuba.wide.ad.jp/Linux/centos/6.6/os/x86_64/ http://ftp.jaist.ac.jp/pub/Linux/CentOS/6.6/os/x86_64/ http://ftp.iij.ad.jp/pub/linux/centos/6.6/os/x86_64/ http://ftp.nara.wide.ad.jp/pub/Linux/centos/6.6/os/x86_64/ http://www.ftp.ne.jp/Linux/packages/CentOS/6.6/os/x86_64/ http://ftp.yz.yamagata-u.ac.jp/pub/linux/centos/6.6/os/x86_64/ http://mirror.nus.edu.sg/centos/6.6/os/x86_64/ http://mirror.vodien.com/centos/6.6/os/x86_64/
となってます。理研あたりを見に行ってみると・・・
Not Found
ギャー!
ということで接続先が消えている場合があります。
こんなときはmirrorlistのアドレスを6.xのようにリビジョンまで指定せず
単に「6」としておけばよいです。最新のリビジョンへの接続先のリストが返ってきます。
http://mirrorlist.centos.org/?release=6&arch=$basearch&repo=os&infra=$infra
リストのうち1つは以下です。6.7が返ってきていますね!
: http://ftp.riken.jp/Linux/centos/6.7/os/x86_64/ :
※といってもなぜか普通にyum updateできることもあります。よくわかっていません。
上記を対応するだけで解決したエラー
(注意)下記エラーは発生する原因が1つではありません。よって上記対応を行っても他に原因があれば以下のエラーメッセージが出力されることがあります。ご注意ください。
errno:14(EFAULT, bad address)で失敗していますね。
Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os&infra=stock error was 14: PYCURL ERROR 7 - "Failed to connect to 2a02:2498:1:3d:5054:ff:fed3:e91a: ネットワークに届きません"
baseurlと言ってますが、別にいじらなくても解決できることもあるようです。
エラー: Cannot find a valid baseurl for repo: base
上でも書いたけどまぁいちおうもう一度書いときます。
file:///mnt/media/repodata/repomd.xml: [Errno 14] Could not open/read file:///mnt/media/repodata/repomd.xml 他のミラーを試します。 エラー: Cannot retrieve repository metadata (repomd.xml) for repository: centos-media. Please verify its path and try again
参考サイト
はにらぼ☆てっく様
yum update でエラーの場合の対応
https://www.honeycomb-lab.co.jp/blog/tech/?p=866
hogehoge foobar Blog Style5 様
yum/wgetをproxy経由で使う方法(CentOS)
http://d.hatena.ne.jp/mrgoofy33/20110125/1295966614
Valgrindの結果の見方、日本語訳、など役に立つことまとめ
勉強がてらメモ。
適宜更新していこう。うん。
Valgrindって?
デバッグやプロファイラなどの複数のツールから構成されるツール群の総称。
メモリリークチェックツールとして有名だと思いますが、
それはValgrindツール群の中のMemcheckというツールによる機能だったのですね。
どんなツールがあるのか?マニュアルを見ると・・・
Memcheck |
|
Cachegrind |
プログラムのキャッシュグラフ、または分岐予測をしてシミュレートする。プログラムを速くするために使うツール。 |
Callgrind |
関数呼び出しをトレースしたりできる。Cachegrindをかぶる部分もあるが、Cachegrindとは別の情報も収集できる。 |
Helgrind |
マルチスレッドのプログラム向け。スレッドエラーを検出できる。 |
DRD |
こちらもマルチスレッドのエラー検出ができる。Helgrindと似ているがアプローチが少々違うようでHelgrindとは異なる問題を検出できるそうな。 |
Massif |
ヒーププロファイラ。メモリ使用量を抑えたい人向け。 |
DHAT |
ヒーププロファイラ。メモリ確保したブロックのライフタイムなどの問題を検出するものらしい。 |
SGcheck |
実験段階のツール。機能はMemcheckと同じだけど、こちらはスタック領域やグローバル領域の配列などに適用できるらしい!使えそう。 |
BBV |
実験段階のツール。基本ブロックベクター生成ツール(なにそれ) |
あと2つあまり使われないツールがあるらしい。
Lackey |
ツールのサンプルコード |
Nulgrind |
ベンチマークやサンプル向けのもの |
筆者はMemcheckくらいしか使ってことがないので
いまいち概要を読んでもピンときませんがなんだか使えそうな気がしますね!
このエントリでは主にデフォルトのオプションであるMemcheckを使っていこうと思います。
Valgrindのインストール
筆者のシステムはCentOS 6.6。
Valgrindが入っていない場合は,yumを使ってインストールしましょう。
yum -y install valgrind
インターネットに接続できないけどCentOS 6のDVDがある人は
以下のエントリを参考にしてDVDメディアをyumのリポジトリに追加しましょう。
便利ですよ。シェルスクリプトをコピペして実行するだけ!1分で終わるよ!
http://d.hatena.ne.jp/taiyakisun/20141201/1417452753
で、以下を実行するとDVDメディアからvalgrindがインストールされます。
yum --disablerepo=\* --enablerepo=centos-media -y install valgrind
結果の見方など
実行するときは基本的にコレ。
valgrind --leak-check=full プログラム プログラムの引数
結果の例はこちら。
==25832== Invalid read of size 4 ==25832== at 0x8048724: BandMatrix::ReSize(int, int, int) (bogon.cpp:45) ==25832== by 0x80487AF: main (bogon.cpp:66) ==25832== Address 0xBFFFF74C is not stack'd, malloc'd or free'd
25832はプロセスID
Memcheck
Invalid read of size 4 - 読んではいけない範囲を4byte分読んだ
こういうときに起こる。
int *p = (int *)malloc( sizeof(int) * 10 ); printf( "%d\n", p[11] );
Invalid write of size 4 - 書き込んではいけない範囲を4byte分書いた
こういうときに起こる。
int *p = (int *)malloc( sizeof(int) * 10 ); p[10] = 5;
上記のInvalid readとかwriteのあとに出ている結果(アドレス)について
int *p = (int *)malloc( sizeof(int) * 10 ); printf( "%d\n", p[11] ); プロセスIDは7885である。 ==7885== Invalid read of size 4 →読んではいけない範囲を4byte分読んだ ==7885== at 0x400580: leakfunc (in /home/valtest/a.out) →アドレス0x400580の関数leakfunc()で発生。 ==7885== by 0x4005A5: main (in /home/valtest/a.out) →さらにそのleakfunc()はアドレス0x4005A5のmain()でコールされている。
==7885== Address 0x51c306c is 4 bytes after a block of size 40 alloc'd
==7885== at 0x4C27A2E: malloc (vg_replace_malloc.c:270)
==7885== by 0x400565: leakfunc (in /home/valtest/a.out)
==7885== by 0x4005A5: main (in /home/valtest/a.out)
→あなたが読んだアドレスは40byte分メモリ確保された位置から4byte分後ろである。
sizeof(int)*10確保してp[11]でアクセスしたから…わかりますね?
after、alloc'dがポイント。
afterがあるということはbeforeもあるよ。
printf( "%d\n", p[-2] );
==7942== Address 0x51c3038 is 8 bytes before a block of size 40 alloc'd
説明は省略します。
不正free()
int *p = (int *)malloc( sizeof(int) * 10 ); free( p ); free( p ); pのアドレスは0x51c3040である。 ==7891== Invalid free() / delete / delete[] / realloc() ==7891== at 0x4C27430: free (vg_replace_malloc.c:446) →解放してはいけないアドレスをfree()もしくはdelete([])、realloc()した。 ==7891== by 0x4005ED: leakfunc (in /home/valtest/a.out) →そのfree()はアドレス0x4005EDのleakfunc()で発生。 ==7891== by 0x4005FD: main (in /home/valtest/a.out) →さらにそのleakfunc()はアドレス0x4005FDのmain()でコールされている。
==7891== Address 0x51c3040 is 0 bytes inside a block of size 40 free'd
==7891== at 0x4C27430: free (vg_replace_malloc.c:446)
==7891== by 0x4005E1: leakfunc (in /home/valtest/a.out)
==7891== by 0x4005FD: main (in /home/valtest/a.out)
→不正なfree()に渡されたアドレスは、過去に確保された40byte分に含まれている部分であり、
すでにfreeされている。そのfreeしたアドレスのメモリ領域の先頭から0byteの位置(つまり先頭)である。
解放済の領域をもう一度解放してまっせということだね。
初期化していない変数を参照
こういうときに起こる。 int a; /* 初期化してない */ printf( "uninitialized value : %d\n", a ); ==7977== Use of uninitialised value of size 8 ==7977== at 0x4E72A9B: _itoa_word (in /lib64/libc-2.12.so) ==7977== by 0x4E75652: vfprintf (in /lib64/libc-2.12.so) ==7977== by 0x4E7E189: printf (in /lib64/libc-2.12.so) ==7977== by 0x4005A7: leakfunc (in /home/valtest/a.out) ==7977== by 0x4005C2: main (in /home/valtest/a.out) →intなのになんで8なんだ? ==7977== Conditional jump or move depends on uninitialised value(s) ==7977== at 0x4E72AA5: _itoa_word (in /lib64/libc-2.12.so) ==7977== by 0x4E75652: vfprintf (in /lib64/libc-2.12.so) ==7977== by 0x4E7E189: printf (in /lib64/libc-2.12.so) ==7977== by 0x4005A7: leakfunc (in /home/valtest/a.out) ==7977== by 0x4005C2: main (in /home/valtest/a.out)
HEAP, LEAKサマリーの見方
==7913== HEAP SUMMARY: ==7913== in use at exit: 0 bytes in 0 blocks →プログラム終了時使用されているヒープは0byte、つまりリークなし! ==7913== total heap usage: 1 allocs, 2 frees, 40 bytes allocated →確保した回数、解放した回数、確保されたメモリ量。 ==7913== All heap blocks were freed -- no leaks are possible →確保されたメモリはすべて解放されておりリークはない。
==7919== HEAP SUMMARY: ==7919== in use at exit: 40 bytes in 1 blocks ==7919== total heap usage: 1 allocs, 0 frees, 40 bytes allocated →プログラム終了時に1ブロック(40byte)分解放してない。 ==7919== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==7919== at 0x4C27A2E: malloc (vg_replace_malloc.c:270) ==7919== by 0x400565: leakfunc (in /home/valtest/a.out) ==7919== by 0x4005BE: main (in /home/valtest/a.out) →「definitely lost」は確実に解放漏れがあるという意味。 ==7919== LEAK SUMMARY: ==7919== definitely lost: 40 bytes in 1 blocks ==7919== indirectly lost: 0 bytes in 0 blocks ==7919== possibly lost: 0 bytes in 0 blocks ==7919== still reachable: 0 bytes in 0 blocks ==7919== suppressed: 0 bytes in 0 blocks →リーク状況まとめ!
SGCheck
Memcheckは主にヒープ領域の不正アクセスを検知するために使用します。
SGCheckはスタック領域、グローバル変数、staticな変数なんかの不正アクセスを検知するものです。
すごいですね。どうやってるんでしょう。
なお、このツールはまだ実験段階だとかなんとか。
サンプルコードとコンパイル
#include <stdio.h> int main() { int z, y, i, a[10], c, d; for ( i=0; i <= 10; ++i ) { a[i] = 42; printf( "a[%d] = %d\n", i, a[i] ); } return 0; }
ビルドは「gcc -g ./上記のソースコードのファイル」で。
不正アクセスは、配列a(サイズ10)の、11番目にアクセスしている箇所です。
不正書き込み
a[i] = 42;
不正読み込み printf( "a[%d] = %d\n", i, a[i] );
エラーメッセージ
==2582== Invalid write of size 4 ==2582== at 0x400546: main (sgcheck.c:9) ==2582== Address 0x1fff000588 expected vs actual: ==2582== Expected: stack array "a" of size 40 in this frame ==2582== Actual: unknown ==2582== Actual: is 0 after Expected
→配列aはサイズ40だが、4byte分不正領域に書き込んでいる、という意味になります。
==2599== Invalid read of size 4 ==2599== at 0x400553: main (sgcheck.c:10) ==2599== Address 0x1fff000588 expected vs actual: ==2599== Expected: stack array "a" of size 40 in this frame ==2599== Actual: unknown ==2599== Actual: is 0 after Expected
→配列aはサイズ40だが、4byte分不正領域に読み込んでいる、という意味になります。
グローバル変数gの場合もほとんど一緒ですが、微妙にエラーメッセージが変わります。
こんな感じです。
==2599== Expected: stack array "a" of size 40 in this frame ↓ ==2700== Expected: global array "g" of size 40 in object with soname "NONE"
静的(static)変数sの場合はこう!
ELFではグローバル変数も静的変数も同じ.bss領域に入るので、ほとんど同じですね!
==2599== Expected: stack array "a" of size 40 in this frame ↓ ==2708== Expected: global array "s" of size 40 in object with soname "NONE"
注意点
その関数のスタックフレーム外の領域を不正参照した場合は、
SGCheckでは検出できないようです…。気を付けないといけないですねぇ(以下例)。
以下は上記サンプルソースのループ条件を「i <= 10」→「i <= 11」としたものです。
a[10] = 42の処理でスタックが破壊され、隣の変数iの値が不正に42になっています。
次のループで、a[42]にアクセスしていますが、関数のスタックフレーム内でないので、
SGCheckはエラーを報告していません。
==2745== Invalid write of size 4 ==2745== at 0x400546: main (sgcheck.c:12) ==2745== Address 0x1fff000588 expected vs actual: ==2745== Expected: stack array "a" of size 40 in this frame ==2745== Actual: unknown ==2745== Actual: is 0 after Expected ==2745== ==2745== Invalid read of size 4 ==2745== at 0x400553: main (sgcheck.c:13) ==2745== Address 0x1fff000588 expected vs actual: ==2745== Expected: stack array "a" of size 40 in this frame ==2745== Actual: unknown ==2745== Actual: is 0 after Expected ==2745== a[10] = 42 a[42] = 0 ==2745== ==2745== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
また、明らかに関数内のスタックフレームを破壊しているのに
エラーが検出されないことがあります…以下例。
サイズ10の配列で、インデックス11に値代入。 a[11] = 42;
まだマニュアルをしっかり読んでいないためかもしれませんが、
原因がわかり次第本エントリーに追記します。
参考サイト
■Valgrind User Manual
http://valgrind.org/docs/manual/manual.html
■Derick Rethans
http://derickrethans.nl/valgrind-null.html
■Stack Overflow
http://stackoverflow.com/questions/27636306/valgrind-address-is-0-bytes-after-a-block-of-size-8-allocd
http://stackoverflow.com/questions/18886298/valgrind-4-bytes-inside-a-block-of-size-8-freed
http://stackoverflow.com/questions/16213746/valgrind-results-of-a-segmentation-fault-program
■仙石浩明の日記
http://www.gcd.org/blog/2007/11/138/
Linuxでgccを使用して共有ライブラリを作成・使用する方法
C/C++でのお話です。
忘れがちなのでまとめておきます。
備忘録
共有ライブラリ作成時
共有ライブラリ使用時
- 先頭のlibと拡張子.soを除いた名前を指定する(例:libsharedlib.soなら-l sharedlib)
- ヘッダファイルやライブラリパスの場所を指定する-Iや-Lはスペースを空けずにオプションの直後にパスを書く(例:-I/home/sample -L./lib)
共有ライブラリの作成
#include <stdio.h> int add( int n1, int n2 ) { printf( "result:%d + %d = %d\n", n1, n2, n1+n2 ); return n1+n2; }
gcc -shared -fPIC -o libsharedlib.so sharedlib.c
共有ライブラリの使用
#include <stdio.h> int main() { int n1 = 10; int n2 = 20; printf( "caller:%d + %d = %d\n", n1, n2, add(n1,n2) ); return 0; }
gcc -I./ -L./ -o main main.c -lsharedlib
正しく実行されれば以下が標準出力に出力されます。
result:10 + 20 = 30 caller:10 + 20 = 30
もし共有ファイル名の先頭が「lib」でない場合は以下のように
共有ライブラリが見つけられずリンカーエラーになってしまいます。
/usr/bin/ld: cannot find -lsharedlib
実行ファイル実行時
ライブラリのパスが通っている場所に共有ライブラリを置くか、
もしくは以下のように環境変数LD_LIBRARY_PATHにパスを指定してから実行します。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
これを実施しないと以下のように共有ライブラリが
見つからない旨のエラーメッセージが出力されます。
./main: error while loading shared libraries: libsharedlib.so: cannot open shared object file: No such file or directory
参考リンク
Visual C++でのDLLの一般的な作成方法(暗黙的リンク)
http://fa11enprince.hatenablog.com/entry/2014/06/20/015808
Linuxで共有ライブラリsoを作ったり使ったりする方法。
http://blog.katty.in/4347
Linux の共有ライブラリを作るとき PIC でコンパイルするのはなぜか
http://0xcc.net/blog/archives/000107.html
たまにしか書かないので、とにかく忘れるJavaプログラミング
C#でも同じようなことをやったような?
忘れがちなことの自分用備忘録!適宜更新!
メソッドの引数はすべて値渡しである
プリミティブ型であろうがオブジェクトの参照渡しだろうが、引数に代入をしてもコール元には影響を与えない!
public void func1( Puyo puyo ) { puyo = redpuyo; // コール元に影響は与えない! } public void func2( int[] array ) { array = another_array; // もちろんコール元に影響は与えない! }
影響を与えるのは、そのメンバを更新したときである。
C++のポインタ渡し(これもポインタのコピー、つまり値渡し)と同じですね。
public void func3( Puyo puyo ) { puyo.color = RED; // コール元のオブジェクトのcolorの値も変わる! }
ややこしいイメージがあったけど、非常にシンプルですね。
C#のrefやoutキーワードみたいなのはないのかな?
CentOSでDVDをyumのリポジトリにするセットアップをするスクリプト
使う場面が限られると思いますが、便利なので。
OSのリビジョンとかによって微妙に内容が異なるかもしれません。
適当に修正してください。
普段はenabled=0としておくことをおすすめします。
#!/bin/sh if [ $# -ne 1 ] then echo "Usage:$0 <CentOS Version>" 1>&2 exit 1 fi mkdir -p /mnt/media mount -r /dev/cdrom /mnt/media if [ ! -e /etc/yum.repos.d/CentOS-Media-User.repo ] then touch /etc/yum.repos.d/CentOS-Media-User.repo echo "[centos-media]" >> /etc/yum.repos.d/CentOS-Media-User.repo echo "name=CentOS Media" >> /etc/yum.repos.d/CentOS-Media-User.repo echo "baseurl=file:///mnt/media" >> /etc/yum.repos.d/CentOS-Media-User.repo echo "gpgcheck=1" >> /etc/yum.repos.d/CentOS-Media-User.repo echo "enabled=1" >> /etc/yum.repos.d/CentOS-Media-User.repo echo "gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-$1" >> /etc/yum.repos.d/CentOS-Media-User.repo fi echo "print yum --disablerepo=\\\* --enablerepo=centos-media list" yum clean all yum --disablerepo=\\\* --enablerepo=centos-media list echo "To use centos-media repo, yum --disablerepo=\\\* --enablerepo=centos-media <yum options>" exit 0
CentOS6なら以下のように実行してください。
./上記スクリプト 6
CentOS7なら以下のように実行してください。
./上記スクリプト 7
/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
の最後の数字を指定しているだけです。
上にも記載してますが、インストールは以下のようにコマンドを実行します。
yum --disablerepo=¥* --enablerepo=centos-media install <インストールしたいパッケージ名など>
7700kcal消費で1kg痩せるのか検証してみました (11月度)
生理的に文法が嫌いなシェルスクリプト
個人的にですが、文法が大嫌いな上にWindows/UNIXで別々のスクリプトを書かなくては
ならないのが非常に馬鹿馬鹿しい。個人ユースならPerlやPythonでいいじゃないか。
という考えだったので今まで徹底的に避けて来ましたが、
どうしても使わなくてはならない状況もあり得る…
ということで、最低限のリファレンスだけ作っておこうと思います。
bashではなく、Bourne Shellを使うことにします。適宜追加です。
すでにファイルが存在していたら数字をずらしてバックアップする
#!/bin/sh if [ $# -ne 2 ] then echo "Usage:$0 <srcfile> <dstbackupfile>" 1>&2 exit 1 fi function file_backup() { srcfile=$1 dstfile=$2 i=0 while [ $i -le 100000 ] do if [ ! -e ${dstfile}.${i} ] then cp -p ${srcfile} ${dstfile}.${i} if [ $? -eq 0 ] then echo "Copying file succeeded(${dstfile}.${i})." break else echo "Copying file failed(${dstfile}.${i})." fi fi i=`expr $i + 1` done } file_backup $1 $2 echo "done." exit 0