2017年6月9日金曜日

ownCloudのマニュアルアップグレード

1ダウンロード
                以下からダウンロード

    2.ラズパイにコピー
              scp owncloud-10.x.x.zip username@192.168.x.xxx:
              最近はtar.bz2なので、
              scp owncloud-10.x.x.tar.bz2 username@192.168.x.xxx:

      3.ラズパイにSSHでログイン
              ssh username@192.168.x.xxx

      4.unzip
              ここからはsuで作業
              su
              cd ~username
              unzip owncloud-10.x.x.zip
              最近はtar.bz2なので、
              tar xf owncloud-10.x.x.tar.bz2

      5.Maintenance mode on
                 sudo -u www-data php occ maintenance:mode —on

      6.rename
                cd /var/www/owncloudのあるところ
                sudo mv ownclouod owncloud_old

      7.stop nginx
                 sudo /etc/init.d/nginx stop

      8.move owncloud
                   sudo mv ~username/owncloud ./owncloud

        9.copy config from old
                sudo cp owncloud_old/config/config.php owncloud/config/config.php

          10.start nginx
                  sudo /etc/init.d/nginx start

            11.Upgrade
                          sudo -u www-data php occ upgrade

              12.Maintenance mode off
                           sudo -u www-data php occ maintenance:mode —off


                2017年6月1日木曜日

                GetTickCountと49.7日問題にハマった

                1秒ごとに実行させたいといった場合

                【普通に思いつくコード】
                DWORD tkNext = ::GetTickCount()+1000;    // 1秒後の時間を計算しておく

                while (bRunning) {
                ::Sleep(1);    // Sleep(0)問題参照
                if(::GetTickCount() <= tkNext){
                continue;    // 1秒経って無ければcontinue
                }
                tkNext = ::GetTickCount()+1000;    // 1秒経ってるので、次の1秒を計算しておく
                // なんらかの処理をする
                }

                これね、何の問題もなさそうに見えたんですわ・・・

                しかし、下部のtkNext = ::GetTickCount()+1000のところで、
                ::GetTickCount()がDWORDの限界付近で、tkNextが0xffffffff付近になったとする
                ループの頭に戻って、GetTickCountした時にDWORDを一周りして、ゼロ以上になっていたら、
                (::Sleep(1)は10ミリ秒以上になるので)
                ::GetTickount() <= tkNextの所が、
                if(10 <= 0xffffffff)になってしまう
                すると、その後、ずっとcontinueしてしまうので、処理が行われなくなる。
                49.7日後に再びGetTickCountがゼロになり、処理まで進まない。
                (0xffffffff/1000/60/60/24 = 約49.7日)
                このプログラムはおよそ49.7日で動かなくなる可能性があるのだ。

                【修正版】
                DWORD tkPrev = GetTickCount();   // 以前実行した時刻を保存しておく
                while (bRunning) {
                ::Sleep(1);
                if(::GetTickCount() - tkPrev < 1000){
                continue;    // 前回実行時刻との差が1秒経って無ければcontinue
                }
                        tkPrev = ::GetTickCount();    // 1秒経ったので、現時刻を保存しとく
                // なんらかの処理をする
                }

                こうやって、::GetTickCount() - tkPrev で判断すれば、DWORDを一回りするタイミングでも問題が無い
                このコードは実はMSDNのGetTickCountでサンプルとして示されたコードとほぼ同一だ。
                このコードの肝は符号拡張の部分なので、怪しいなと思ったらDWORD変数を作ってループさせるプログラムでも作って検証してみると良い。

                2017年5月16日火曜日

                タチカワ 新ペン先 スクールG

                自分はプロではないけど漫画を描いていたこともあり、
                Gペンや丸ペンなど使いまくっていた。
                最初は原稿用紙にポタリ落とすこともあったけど、
                適切な量もわかって、ほぼミスも無くなった。
                しかし、もっと細い線がもっと高速に描きたくなって、
                ロットリングのラピッドグラフ、イソグラフと使ってきた。
                A0の紙にイソグラフでカケアミなどの模様を一面描き込んで、
                スクリーントーンと間違われたこともある。

                ゲーム業界時代はイソグラフでメモを取っていた。
                相当長い間使ったので、プラスチックの蓋が経年変化で変形し、
                まさか壊れることはないと思っていたイソグラフ本体にヒビが入って壊れた。
                プラスチックは経年変化するのだ。

                んで、メモや絵を描く道具として万年筆に目を向けた。
                筆圧が出るところもイソグラフより魅力的だ。
                俺は、はっきり言って、
                ペン先の描き味、インクの質、ペンの重心など、こだわりは半端ない。
                普通にメモを取るだけでなく、きっちりしっかり画材としても見る。
                画材になれないのだったらまったく評価出来ない。

                最近LAMYの万年筆を使っているのだけど、
                EF(極細)なのに太すぎる!
                AURORAのイプシロンよりは書きやすいが、
                付属インクも水性とかありえんだろ!
                上から色塗れねぇじゃねぇか、アホなのか?
                水に浸かったらメモが全部読めなくなるぞ?
                今はパイロットのインクに変えたので、
                水に濡れてメモが読めなくなる恐れは無くなったが、
                この万年筆作った連中は、メモという自分の記録が大事じゃないのか?
                数年で色褪せるようなインク作るんじゃねぇよ

                どこかにGペンの書き心地の万年筆は無いもんだろうか・・・
                いつでも使えて、Gペンみたいに細字から太字まで書きまくれるようなら最高なんだけどなぁ

                と思っていたら見つけた
                タチカワ 新ペン先 スクールGだ。

                こいつ、レビューはいまいちなんだけど、
                絵かきにとっては中々良い。
                抑揚の付けられない万年筆よりは面白いし、
                絵かきならこのペンは何の苦労もなく使えるだろう。
                かなりおすすめである。



                2017年5月12日金曜日

                COMのCreateInstanceとAddRefとRelease

                COMではまず、クラスをCreateInstanceして、QueryInterfaceして、ほっとけば呼び出し側の参照が切れたときに消える。

                CreateInstanceでは参照カウントm_dwRefはゼロのまま。
                QueryInterfaceではm_dwRefがインクリメントされる。
                呼び出し側が参照をやめれば、勝手にm_dwRefがデクリメントされ、
                CreateInstanceで作ったクラスのデストラクタが呼ばれる。
                ちなみにデクリメントしたい場合は、Releaseを呼ぶ。

                QueryInterfaceせず、呼び出し側に参照をさせないのであれば、
                CreateInstanceして、色々使って、最後に消す必要も無く勝手に消えるんだろうと思っていた。
                だってm_dwRefはゼロのままだからね?

                ところが、これだと消えてくれないのだ。
                CreateInstance
                AddRef
                いらなくなったらRelease
                これでCreateInstanceで作ったインスタンスのデストラクタが動く。

                AddRefでm_dwRefがインクリメントされ、
                Releaseでデクリメントされる。
                それだけにしか見えないんだけど、それやらないとデストラクタが動かない。

                _bstr_tでメモリ解放漏れ

                ある日の俺は、ATL で COM作っていた。
                クラスのメンバー変数のように_bstr_tを使っていたのだが、
                クラスが消えるときに_bstr_tの内部の値が消えてくれなかった。

                何でかというと_bstr_tはクラスであって、
                オペレータのイコールをオーバーロードしてあって、
                内部変数 Data_t に new して値をメモリに確保して入れてる。

                それが、デストラクタで消えるかと思ったら、消してないんだよね・・・
                なんでnewしてんだ・・・

                COMで使う時は、ComBSTRのがいいのかもしんない。

                ちなみに消すためには、
                _bstr_tのAssign(NULL)を呼び出す。
                そのまま放っておくとメモリー解放漏れになる。

                誰だ_bstr_tが安全ぽいとか書いた奴!

                あー、ここでも同じことで悩んでるやつ発見
                http://stackoverflow.com/questions/13011179/bstr-t-memory-leak
                日本では鵜呑みにする奴が多いが、MSのコードはバグが多いぞ
                よく注意するべし!

                2017年5月11日木曜日

                letsencrypt

                会社のサイトを作ったので、letsencryptで証明書を作ったのだが、
                Androidで見れないと言われた。
                調べてみたら、fullchainじゃないとダメらしい。
                その他のデバイスでは不具合を聞かなかった。
                面倒だなぁAndroid

                2017年5月7日日曜日

                M4V on ownCloud 9.1.5

                RaspberryPiにセットアップしたownCloudには少し問題があって、
                M4Vが再生できなかったのだが、、、
                ちょっと前にffmpegを入れても再生できなかったのだ。
                んで、調べてみたら、作者同士が罵り合ってm4vが再生できなかったとかなんだとかいう記事を見つけて、そうなの?残念ねと思っていた。
                ところが、こないだ9.1.5にバージョンアップしてから試しに再生してみたらきちんと再生できた。
                iPhoneのSafariでも再生できたので、多分どの端末でもいけるだろう。

                M4VはApple独自の規格らしい。
                しかし、過去の記事で書いた通り、mediaTombでは同じデコードで再生できたのだし、
                中身ほぼ一緒と考える人がいるのも仕方ないのかもしれない。
                なんにせよ、今はm4vもownCloudで再生できるようになったのでよかったよかった。


                2017年4月25日火曜日

                WPF Popupでお困りの皆様へ

                https://social.msdn.microsoft.com/Forums/vstudio/en-US/f0502813-9c4f-4b45-bab8-91f98971e407/popup-popupstaysopen-togglebutton-and-data-binding-helpful-tip?forum=wpf

                WPFでPopupは非常に扱いづらい。

                Popup は StaysOpen=true にしておくとフォーム外をクリックしても閉じてくれないし、フォームをドラッグすると Popup だけ置いてけぼりになる。

                あちこちのサイトを見ると、ToggleButton の IsChecked にバインドしろとか書いてあるけど、お前らそんなに Popup をトグルボタンでオープンしたいのか?

                上記URLの解は非常にシンプルだ。

                自分は TextBox の横に Popup を配置して、TextBoxのPreviewMouseLButtonClick で IsOpen=True にし、 LostFocus で IsOpen=Falseにする処理も追加した。

                まぁ、騙されたと思ってやってみて欲しい。
                TextBox をマウスでクリックすると Popup が開き、
                フォーム上のどこかをクリックすると Popup は消える。
                フォームをドラッグしようとしてもきちんと消えるし、
                フォーム外のどこかをクリックしても消えてくれる。

                2016年11月19日土曜日

                ownCloud BackupScript一部変更


                せっかく6時間ごとにSQLDUMPしているのに無くなってしまうのはもったいないので、
                `date +"%Y%m%d_%H%M%S"`にしておいた。

                んで、バックアップで残す日付は +3 じゃなくて +0 にしておいた。
                わりとSQLDUMPの容量がでかくて、19Mくらいになってる。

                2016年11月12日土曜日

                ownCloud on Raspberry Pi with Backup

                今日、HDDが届いたのでバックアップするように設定する。
                まずは普通につなぐ

                sudo fdisk -l

                Device     Boot Start        End    Sectors  Size Id Type

                /dev/sdb1          64 3907029119 3907029056  1.8T  7 HPFS/NTFS/exFAT

                今度はsdb1なんだな

                では、フォーマット
                sudo mkfs.ext4 -m 0.001 /dev/sdb1

                マウント場所を作る
                sudo mkdir /mnt/hdd2

                んで、マウント
                sudo mount /dev/sdb1 /mnt/hdd2

                UUIDを確認
                sudo blkid /dev/sdb1

                fstabに書き込み
                sudo vi /etc/fstab
                UUID="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" /mnt/hdd2 ext4 defaults 0 0

                XXXのとこはUUIDを書く

                バックアップ用のフォルダを作る
                mkdir /mnt/hdd2/backup
                mkdir /mnt/hdd2/log
                mkdir /mnt/hdd2/sqldump

                んで、Scripts作る
                sudo vi scripts/oc-backup.sh

                #!/bin/bash

                date
                sudo rsync -avz --delete /var/www/owncloud/config /mnt/hdd1/data /mnt/hdd2/backup | tail -n 2

                sudo mysqldump --lock-tables -h localhost -u ユーザ名 -pXXXXXXXX データベース > /mnt/hdd2/sqldump/owncloud-dbbackup_`date +"%Y%m%d"`.bak | tail -n 2

                exit 0

                んで、スクリプトにx付けとく
                chomod +x oc-backup.sh


                Cronに書いとく
                sudo crontab -e

                0 0,6,12,18 * * * /home/UserName/scripts/oc-backup.sh >> /mnt/hdd2/log/oc-backup.log

                これで、6時間おきにバックアップが行われる。
                sqldumpは日付ごとに作られるから、たまに様子見て消さないと・・・てのが面倒な気がする・・・
                ので、以下のコマンドもさっきのスクリプトに追加


                sudo find /mnt/hdd2/sqldump/ -name '*.bak' -mtime +3 -delete





                2016年11月7日月曜日

                ownCloud on Raspberry Pi

                こちらを参考に、ownCloudをRaspberryPiModel3に設定した。
                https://normally.online/2016/04/29/owncloud-9-0-1-on-raspberry-pi-3-step-by-step/

                LetsEncryptてのがあるんですね、知りませんでした。
                証明書はCronで毎月更新するようにしておきました。
                やり方はまるっきりサイトの通りです
                UserNameのホームにletsencrypt入れてるので、それを動くようにしときました。


                00 06 24 * * /etc/init.d/nginx stop && /home/UserName/letsencrypt/letsencrypt-auto renew --force-renew && /etc/init.d/nginx start


                DDNSはこちらのサイトを参考に設定しました。
                http://qiita.com/ukatawagatik/items/d087008a14beb509b846

                まだバックアップ先が無いので、
                今度HDDを増設し、rsyncで同期させたり、cronでDBのバックアップしとかないとなぁ

                それにしてもownCloudはめちゃ便利、
                去年Pydioサーバが落雷のサージで壊れてから、
                ようやくownCloudで会社用の共有スペースが用意できました。

                それとHDDの停止についてはこちらを参考にしました。
                http://kassyjp.ninja-web.net/ras/jessie/spindown.htm

                適当な場所に以下のスクリプトを作成

                #!/bin/sh

                if [ $# -lt 2 ]; then
                        echo "not enough arguments supplied."
                        echo "hdd_spindown.sh [UUID] [INTERVAL]"
                        exit 0
                fi

                disk=`findfs UUID="$1"`
                interval=$2

                count=$interval
                up=1

                if [ -z $disk ]; then
                        #echo "findfs error"
                        exit 1
                fi

                disk=`echo "$disk" |sed -e "s@/dev/@@"`

                state=`grep " $disk " /proc/diskstats`

                while [ true ]; do
                        sleep 10
                        count=$(($count-10))
                        newstate=`grep " $disk " /proc/diskstats`
                        if [ "$state" = "$newstate" ]; then
                                if [ $count -lt 0 ]; then
                                        count=$interval
                                        if [ $up = 1 ]; then
                                                #echo -e "spin-down"
                                                sync
                                                state=`grep " $disk " /proc/diskstats`
                                                sdparm --command=stop -r /dev/$disk > /dev/null 2>&1
                                                up=0
                                        fi
                                fi
                        else
                                #echo -e "drive is up"
                                count=$interval
                                state="$newstate"
                                up=1
                        fi
                done


                んで、サービスで停止するように設定
                sudo vi /lib/systemd/system/user_hdd_spindown.service

                [Unit]
                Description=hdd spindown by sdparm
                After=mnt-hdd1.mount

                [Service]
                ExecStart=/path to script/usbhdd_spindown.sh XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 60 > /dev/null 2>&1
                KillMode=process
                Type=simple
                Restart=always

                [Install]
                WantedBy=multi-user.target

                なぜか、元記事はRestart=noだったので、alwaysに変えときました。