ubuntu で do-release-upgrade が失敗する

proxy環境下にあると以下のようなエラーがしばらく繰り返して失敗します。

0% [ヘッダの待機中です]
0% [ヘッダの待機中です]
0% [ヘッダの待機中です]
エラー http://security.ubuntu.com/ubuntu/ xenial-security/main linux-headers-4.4.0-71 all 4.4.0-71.92
  接続失敗 [IP: 192.168.0.1 8080]
0% [ヘッダの待機中です]

どうやらProxyがおそすぎてタイムアウトするらしいです。

まずは速いミラーに変えます。 /etc/apt/source.list/etc/apt/source.list.distUpgradeを日本の早そうなミラーに書き換えました。

launchpad.net

それでもでかいファイルは駄目っぽいので、手動で落として /var/cache/apt/archives に放り込んだら進みだした。

まったくもう。まともなプロキシにするだけでどれだけ生産性が向上することやら。(´Д`)ハァ…

参考

srad.jp

NuGetパッケージのキャッシュをクリアする

自分が悪いのですが、snapshotを作らずに同じバージョンのパッケージをNexusリポジトリにどんどん上書きしていたら、参照しているプロジェクト側で何度消して入れ直しても古いパッケージが入ってしまうようになった。

キャッシュは、C:\Users\ユーザ名\AppData\Local\NuGet にあるというのはぐぐってわかったのだがそこにもファイルはなく。。。
Nexusのキャッシュをクリアしたり、再起動したりどうにも行き詰まっていたが結局はnugetコマンドで解決しました。

結論としては、NuGetのキャッシュはあちこちにある!ということらしいです。(;´д`)トホホ…

  • キャッシュの一覧を表示する
C:\home\gozu\projects\hogehoge\src>nuget locals all -list
http-cache: C:\Users\gozu\AppData\Local\NuGet\v3-cache
packages-cache: C:\Users\gozu\AppData\Local\NuGet\Cache
global-packages: C:\Users\gozu\.nuget\packages\
temp: C:\Users\gozu\AppData\Local\Temp\NuGetScratch
  • キャッシュをクリアする
C:\home\gozu\projects\hogehoge\src>nuget locals all -clear
Clearing NuGet HTTP cache: C:\Users\gozu\AppData\Local\NuGet\v3-cache
Clearing NuGet cache: C:\Users\gozu\AppData\Local\NuGet\Cache
Clearing NuGet global packages cache: C:\Users\gozu\.nuget\packages\
Local resources cleared.

これで解決しました。

Visual Studio 2015にしたらNuget restoreで参照設定が復元されなくなった

Jenkinsで流すと、nuget restoreは一見正常に終了しているが次のMSBuildでエラーになります。

エラーは次の通り。(ちょっと長いけど)

ResolveAssemblyReferences:
  プライマリ参照 "log4net" です。
C:\Program Files\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1820,5): warning MSB3245: この参照を解決できませんでした。アセンブリ "log4net" が見つかりませんでした。アセンブリが間違いなくディスクに存在することを確認してください。 コードにこの参照が必要な場合、コンパイル エラーが発生する可能性があります。 [c:\jenkins\workspace\Foo_bar_develop-CTIV4IL2JPHXPYVJDTYNNVX42T665ZR7U5MNMTNIGCKMRODFHMAA\src\bar\bar.csproj]
          検索パスは "{TargetFrameworkDirectory}" です。
          "C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\log4net.winmd" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\log4net.dll" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\log4net.exe" を考慮しましたが、存在しませんでした。
          検索パスは "{Registry:Software\Microsoft\.NETFramework,v4.0,AssemblyFoldersEx}" です。
          AssemblyFoldersEx の場所が考慮されました。
          検索パスは "{AssemblyFolders}" です。
          "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\log4net.winmd" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\log4net.dll" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\log4net.exe" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Microsoft SQL Server\120\SDK\Assemblies\log4net.winmd" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Microsoft SQL Server\120\SDK\Assemblies\log4net.dll" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Microsoft SQL Server\120\SDK\Assemblies\log4net.exe" を考慮しましたが、存在しませんでした。
          "C:\Program Files\IIS\Microsoft Web Deploy V3\log4net.winmd" を考慮しましたが、存在しませんでした。
          "C:\Program Files\IIS\Microsoft Web Deploy V3\log4net.dll" を考慮しましたが、存在しませんでした。
          "C:\Program Files\IIS\Microsoft Web Deploy V3\log4net.exe" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\log4net.winmd" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\log4net.dll" を考慮しましたが、存在しませんでした。
          "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\log4net.exe" を考慮しましたが、存在しませんでした。
          検索パスは "{GAC}" です。
          GAC で見つからなかった "log4net" を考慮しました。
          検索パスは "{RawFileName}" です。
          "log4net" をファイル名として扱いましたが、存在しませんでした。
          検索パスは "bin\x86\Release\" です。
          "bin\x86\Release\log4net.winmd" を考慮しましたが、存在しませんでした。
          "bin\x86\Release\log4net.dll" を考慮しましたが、存在しませんでした。
          "bin\x86\Release\log4net.exe" を考慮しましたが、存在しませんでした。
  AssemblyFoldersEx の場所:"{Registry:Software\Microsoft\.NETFramework,v4.0,AssemblyFoldersEx}"
          C:\Program Files\NUnit 2.6.3\bin\framework\
          C:\Program Files\Microsoft Visual Studio 14.0\Common7\IDE\ReferenceAssemblies\v4.0\
          C:\Program Files\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v4.0\
          
          C:\Program Files\Reference Assemblies\Microsoft\VBPowerPacks\v10.0\
          C:\Program Files\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Prototyping\Libraries\
          C:\Program Files\Microsoft SDKs\Expression\Extensions\FXG\Libraries\.NETFramework\v4.0\
          C:\Program Files\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries\
          C:\Program Files\Microsoft Visual Studio 14.0\Common7\IDE\ReferenceAssemblies\v2.0\
          C:\Program Files\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v2.0\
          C:\Program Files\Reference Assemblies\Microsoft\VBPowerPacks\v10.0\
          C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop
          C:\Program Files\Common Files\Microsoft Shared\MSEnv\PublicAssemblies\
          C:\Program Files\Microsoft Chart Controls\Assemblies
GenerateTargetFrameworkMonikerAttribute:
すべての出力ファイルが入力ファイルに対して最新なので、ターゲット "GenerateTargetFrameworkMonikerAttribute" を省略します。
CoreCompile:
  C:\Program Files\MSBuild\14.0\bin\csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /platform:x86 /errorreport:prompt /define:TRACE /highentropyva- /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Configuration.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Xml.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Xml.Linq.dll" /filealign:512 /optimize+ /out:obj\x86\Release\bar.dll /ruleset:"C:\Program Files\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\\Rule Sets\ManagedMinimumRules.ruleset" /target:library /utf8output Properties\AssemblyInfo.cs src\Ibar.cs src\bar4net.cs src\barBase.cs src\barManager.cs "C:\Users\jenkins\AppData\Local\Temp\.NETFramework,Version=v4.0.AssemblyAttributes.cs"
  Using shared compilation with compiler from directory: C:\Program Files\MSBuild\14.0\bin
src\bar4net.cs(11,17): error CS0246: 型または名前空間の名前 'log4net' が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)。 [c:\jenkins\workspace\Foo_bar_develop-CTIV4IL2JPHXPYVJDTYNNVX42T665ZR7U5MNMTNIGCKMRODFHMAA\src\bar\bar.csproj]
プロジェクト "c:\jenkins\workspace\Foo_bar_develop-CTIV4IL2JPHXPYVJDTYNNVX42T665ZR7U5MNMTNIGCKMRODFHMAA\src\bar\bar.csproj" (Rebuild ターゲット) のビルドが終了しました -- 失敗。
プロジェクト "c:\jenkins\workspace\Foo_bar_develop-CTIV4IL2JPHXPYVJDTYNNVX42T665ZR7U5MNMTNIGCKMRODFHMAA\src\bar.sln" (Rebuild ターゲット) のビルドが終了しました -- 失敗。

ビルドに失敗しました。

Jenkinsのビルド用スレーブでVisual Studioを起動してからUpdate-Package -reinstallすれば直った。
が、CI的にはVS開いてゴニョゴニョしたくないのでスレーブのcsprojファイルを参考に以下のように元ファイルを修正したら、nuget restoreで参照設定が壊れなくなった!

  <ItemGroup>
    <Reference Include="log4net">
      <HintPath>..\packages\log4net.2.0.7\lib\net40-full\log4net.dll</HintPath>
      <Private>True</Private>
    </Reference>
  </ItemGroup>

でもこれってファイルの数が増えたらたまんないな。。。
もっといいやり方がありそうだけど。いや、あるべきだ!

Visual Studio 2015 で古いプロジェクトを開いた時に「参照」が壊れた

現象

Visual Studio 2012のプロジェクトを2015で開いたら、参照が全部壊れているプロジェクトがあった。(全部ではない)

  • SystemとかSystem.Coreとか基本的なやつやlog4netといったnuget管理の物も黄色の!がでて参照できなくなっている
    • 参照からランタイムを選んでプロパティを表示するとバージョンが0.0.0.0になっている
  • 参照の追加で選び直しても駄目
  • 対象のランタイムを切り替えても駄目

解消方法

結局、csprojファイルを直接エディタで開いて直しました。
以下の部分を削除します。

  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
  </Target>

ちなみにソリューションファイル(sln)の変換は上手くいってました。

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2012 for Windows Desktop
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 14 for Windows Desktop
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1

C#でWindowsのシステム環境変数を取得するときに値として埋め込まれている環境変数を展開しないで取得する

題名長い (;´д`)

環境変数を取得して改変してセットしたいときに値として埋め込まれた環境変数が展開されてしまうと不都合があると思います。

システム環境変数Pathを取得して変更する例

システム環境変数(例えばPath)を取得したい場合、いくつかやり方があるけど以下のようにすると簡単ですよね。

string env = "Path";
string value = Environment.GetEnvironmentVariable(env, EnvironmentVariableTarget.Machine);
Console.WriteLine(string.Format("{0}={1}", env, value);

以下のような値が取れたとします。

Path=C:\Program Files\Java\jre1.8.0_111\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\ProgramData\chocolatey\bin

ただ環境変数GUIから確認すると、以下のようになっています。

Path=%JAVA_HOME%\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\ProgramData\chocolatey\bin

取得した値に追加のパスを入れて保存したら%JAVA_HOME%\binC:\Program Files\Java\jre1.8.0_111\binに変わってしまいますよね。これは嬉しくありません。

というわけで、レジストリから取得すれば展開前の値が取れました。

using Microsoft.Win32;

string env = "Path";
RegistryKey reg = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment");
string value = (String)reg.GetValue(env, "", RegistryValueOptions.DoNotExpandEnvironmentNames);
Console.WriteLine(string.Format("{0}={1}", env, value);

GetValueの第3引数にRegistryValueOptions.DoNotExpandEnvironmentNames渡すと展開されずに取得できます。

意外と手こずったのでφ(..)メモメモ

IE 11で何故か互換表示になってしまう場合にデフォルト(Edge)に戻す

会社の中でIE使っているときはイントラネットゾーンになって、なんか互換表示になっていることがあります。

その時は、metaタグに

<meta http-equiv="X-UA-Compatible" content="IE=edge">

と入れることで元に戻るのですが、なんか戻らない時があるんですよね。

そんなときは、上の方(charsetのすぐ下とか)に書いてみると直ることがあります。

<head>
    <meta charset="UTF-8">
    .
    .
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    .

↓↓↓

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    .
    .
    .

まったく、何なんすかねこれヽ(`Д´)ノプンプン

Groovyでログから特定区間の処理時間を計算する

障害調査とかログから処理時間を抽出するというのをごにょっとやったのでメモを残しておきます。(書いとかないと絶対忘れるやつだし)

ログファイルから欲しい情報を抜き出す

スタックトレースを起点に処理時間を抽出しようとするとその行には日付などの情報が入って無くて前後数行欲しいってありますよね。

$ ag --nonumbers -B4 -A1 -G "hogehoge.log*" "^System\.Data\.SqlClient\.SqlException"
  • -B4 は前4行を抜き出すということです
  • -A1 は後1行を抜き出すということです
  • -G正規表現を使うようにしてます

2点間の処理時間を調べる

上で抽出した中間ファイルからExcelで処理するようのCSVを作成します。
使い慣れたGroovyでやってみます。使い捨てのスクリプトなので適当に書いてます。

  • 取り敢えず半角スペースでsplitしながらぐるぐる回します
new File('hogehoge.txt').splitEachLine(' ') { logs ->
    // 処理
}
  • 上の処理の中身(回しながら欲しい2点間のログを抽出)
    def format = "yyyy-MM-dd HH:mm:ss,SSS"

    comment = logs[7]
    if (!comment) {
        //println "null"
    }
    else if (comment.contains("アプリケーションを開始")) {
        start = new Date().parse(format, "${logs[3]} ${logs[4]}")
    }
    else if (comment.contains("DBの接続に失敗しました")) {
        end = new Date().parse(format, "${logs[3]} ${logs[4]}")
        time = end.toTimestamp().getTime() - start.toTimestamp().getTime()
        println "${logs[0]}\t${logs[3]} ${logs[4]}\t${time}"
    }

logs[7]にログの文字列が入ってくる想定なので計測したい2点間のキーワードを引っ掛けて、ログの時間を取得して処理時間を計算します。
この時に、.NETのlog4netで出している形式をformatで定義してData().parseで変換してます。
yyyy-MM-dd HH:mm:ss,SSS こんな形式で実際には2017-01-16 12:34:56,789って感じのやつですね。
timeに処理時間を入れてます。計算するときは、toTimestamp().getTime()を使ってミリ秒単位で結果が出るようにしています。

って言うか、最初からログに処理時間を出すようにして欲しいデス!!!

おまけ

  • ログが巨大なのでちょっと1万行くらい処理して様子をみたいとかあるのですが、Groovyのeachの中ではbreak出来ないので無理やり抜けるようにしてました。
def i = 0
new File('hogehoge.txt').splitEachLine(' ') { logs ->
    // 処理
    i++
    if (i > 10000) { System.exit(0) }
}

他にいいやり方があれば教えて欲しい・・・。

  • 一応、ソース付けておきます。
def i = 0
def format = "yyyy-MM-dd HH:mm:ss,SSS"
def start
def end
def time
def comment

new File('hogehoge.txt').splitEachLine(' ') { logs ->
    comment = logs[7]
    if (!comment) {
        //println "null"
    }
    else if (comment.contains("アプリケーションを開始")) {
        start = new Date().parse(format, "${logs[3]} ${logs[4]}")
    }
    else if (comment.contains("DBの接続に失敗しました")) {
        end = new Date().parse(format, "${logs[3]} ${logs[4]}")
        time = end.toTimestamp().getTime() - start.toTimestamp().getTime()
        println "${logs[0]}\t${logs[3]} ${logs[4]}\t${time}"
    }
    // 1万行ほどやってみるときは下のコメントを外す
    //i++
    //if (i > 10000) { System.exit(0) }
}