javaでjavaagentとagentlibを調査してみる
http://docs.oracle.com/javase/6/docs/technotes/tools/solaris/java.html
の-agentlib, -javaagentの項目について調べてみた
あれ、なんか俺agentlibとjavaagentを勘違いしている、、、、?
-agentlib
-agentlib:hprofや-agentlib:jdwpなどプロファイラやデバッガなどを利用するネイティブライブラリを指定する
詳しくはJVMTI(Java Virtual Machine Tools Interface)を参照することつまりCやC++を使って、VMにアクセスしてプロファイル情報などを引き抜いたり、デバッグ用に挙動を操作したりすることができるらしい
JVMTIの日本語DOC
http://java.sun.com/javase/ja/6/docs/ja/platform/jvmti/jvmti.html#starting
JVMTIを利用する
http://www.02.246.ne.jp/~torutk/javahow2/jvmti.html
-javaagent
java.lang.instrumentパッケージを使ってバイトコードをVM起動時に動的に書き換えたりできる。
下記さくらばさんの書き込みがそのままです
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=26578&forum=12
以下バイトコードを動的に操作 Instrumentationを参考にjavaagentについて色々動作を試してみる
eclipseのworkspaceにできたクラスファイルをjarにまとめる
$ cd ~/Documents/workspace/lick_up_jvm/target/classes $ jar cvf sample.jar jp/co/watanabe_yusaku/instrument/InstrmentTest.class マニフェストが追加されました InstrmentTest.classを追加中です(入=982)(出=528)(46%収縮されました)
いったんjarを展開してマニフェストファイルにPremain-Classを追記する
$ jar xvf sample.jar META-INF/が作成されました \META-INF/MANIFEST.MFが展開されました \jp/co/watanabe_yusaku/instrument/InstrmentTest.classが展開されました $ vim META-INF/MANIFEST.MF ↓追記 Premain-Class: jp.co.watanabe_yusaku.instrument.InstrmentTest $ jar cvfm sample.jar META-INF/MANIFEST.MF jp/co/watanabe_yusaku/instrument/InstrmentTest.class マニフェストが追加されました jp/co/watanabe_yusaku/instrument/InstrmentTest.classを追加中です(入=982)(出=528)(46%収縮されました)
実行してみる
$ java -javaagent:sample.jar jp/co//watanabe_yusaku/main/HelloWorld class java.util.HashMap$EntryIterator class java.lang.Boolean 略 Hello, World!
ちゃんとHelloWorldクラスのmainが実行される前にInstrmentTestクラスのpremainが実行されてるようだ。
この仕組みを使えば稼働中のアプリケーションの構造(設定ファイルなどを含む)を一切変更せずに挙動を変更することができる。
以下のようなコードをjarで固めてjavaagent指定すると全てのメソッドの実行時間をミリ秒で出力することができた。
import java.io.ByteArrayInputStream; import java.io.IOException; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; import java.security.ProtectionDomain; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; public class MethodTimer { private static ClassPool classPool; @SuppressWarnings("rawtypes") public static void premain(String agentArgs, Instrumentation inst) { classPool = ClassPool.getDefault(); inst.addTransformer(new ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { try { ByteArrayInputStream stream = new ByteArrayInputStream(classfileBuffer); CtClass ctClass = classPool.makeClass(stream); CtMethod[] ctMethods = ctClass.getDeclaredMethods(); for(CtMethod ctMethod : ctMethods) { ctMethod.addLocalVariable("start", CtClass.longType); ctMethod.insertBefore("start = System.currentTimeMillis();"); ctMethod.insertAfter("System.out.println(\"" + ctClass.getName() + "." + ctMethod.getName() + "()" + ":exec time = \" + (System.currentTimeMillis() - start));"); } return ctClass.toBytecode(); }catch(CannotCompileException | IOException e) { IllegalClassFormatException ecfe = new IllegalClassFormatException(); ecfe.initCause(e); throw ecfe; } } }); } }
マニフェストファイルは
Premain-Class: MethodTimer Boot-Class-Path: javassist.jar Can-Redefine-Classes: true
mainクラスは
public class HelloWorld { public static void main(String[] args) throws Exception{ HelloWorld h = new HelloWorld(); h.execute(args); } public void execute(String[] args) throws Exception{ this.say("Hello, World0"); this.say("Hello, World1"); Thread.sleep(3000); this.say("Hello, World2"); this.say("Hello, World3"); } public void say(String str) { System.out.println(str); } }
実行ディレクトリにjavasisst.jarとsample.jarを配置してから実行すると
java -javaagent:sample.jar HelloWorld sun.launcher.LauncherHelper.makePlatformString():exec time = 0 sun.launcher.LauncherHelper.getMainMethod():exec time = 0 sun.launcher.LauncherHelper.checkAndLoadMain():exec time = 6 Hello, World0 HelloWorld.say():exec time = 1 Hello, World1 HelloWorld.say():exec time = 1 Hello, World2 HelloWorld.say():exec time = 0 Hello, World3 HelloWorld.say():exec time = 0 HelloWorld.execute():exec time = 3004 HelloWorld.main():exec time = 3004
AOPを導入するまでもないけど、ちょっと本番環境で設定ファイルなどを含む環境などを一切変更しないでプロファイリングしたい時に便利かもしれないですね
自宅サーバのRAID障害が出た日
以前構築した自宅サーバのRAID環境から障害通知メールが来た。
件名:mdadm monitoring
This is an automatically generated mail message from mdadm running on localhost.localdomain A Fail event had been detected on md device /dev/md0. It could be related to component device /dev/sdc1. Faithfully yours, etc. P.S. The /proc/mdstat file currently contains the following: Personalities : [raid1] md0 : active raid1 sdc1[2](F) sdb1[0] 976759936 blocks [2/1] [U_] unused devices:
/var/log/messagesを確認してそれっぽいエラーが出ているのがここらへん。
ar 18 05:43:04 localhost kernel: SCSI device sdc: 1953525168 512-byte hdwr sectors (1000205 MB) Mar 18 05:43:11 localhost kernel: sdc: Write Protect is off Mar 18 05:43:12 localhost kernel: SCSI device sdc: drive cache: write back Mar 18 05:44:12 localhost kernel: ata2.01: exception Emask 0x10 SAct 0x0 SErr 0x400100 action 0x6 frozen Mar 18 05:44:12 localhost kernel: ata2: SError: { UnrecovData Handshk } Mar 18 05:44:12 localhost kernel: ata2.01: cmd 35/00:00:3f:05:c3/00:04:09:00:00/f0 tag 0 dma 524288 out Mar 18 05:44:12 localhost kernel: res 40/00:cf:61:05:c3/40:03:09:00:00/f0 Emask 0x14 (ATA bus error) 169,51 34% Mar 18 05:43:04 localhost kernel: sdc: Current [descriptor]: sense key: Medium Error Mar 18 05:43:04 localhost kernel: Add. Sense: Unrecovered read error - auto reallocate failed Mar 18 05:43:04 localhost kernel: Mar 18 05:43:04 localhost kernel: Descriptor sense data with sense descriptors (in hex): Mar 18 05:43:04 localhost kernel: 72 03 11 04 00 00 00 0c 00 0a 80 00 00 00 00 00 Mar 18 05:43:04 localhost kernel: 09 c3 05 61 Mar 18 05:43:04 localhost kernel: end_request: I/O error, dev sdc, sector 163775841 Mar 18 05:43:04 localhost kernel: ata2: EH complete Mar 18 05:43:04 localhost kernel: SCSI device sdc: 1953525168 512-byte hdwr sectors (1000205 MB) Mar 18 05:43:11 localhost kernel: sdc: Write Protect is off Mar 18 05:43:12 localhost kernel: SCSI device sdc: drive cache: write back Mar 18 05:44:12 localhost kernel: ata2.01: exception Emask 0x10 SAct 0x0 SErr 0x400100 action 0x6 frozen Mar 18 05:44:12 localhost kernel: ata2: SError: { UnrecovData Handshk } Mar 18 05:44:12 localhost kernel: ata2.01: cmd 35/00:00:3f:05:c3/00:04:09:00:00/f0 tag 0 dma 524288 out Mar 18 05:44:12 localhost kernel: res 40/00:cf:61:05:c3/40:03:09:00:00/f0 Emask 0x14 (ATA bus error) 169,51 33% Mar 18 05:43:04 localhost kernel: sdc: Current [descriptor]: sense key: Medium Error Mar 18 05:43:04 localhost kernel: Add. Sense: Unrecovered read error - auto reallocate failed Mar 18 05:43:04 localhost kernel: Mar 18 05:43:04 localhost kernel: Descriptor sense data with sense descriptors (in hex): Mar 18 05:43:04 localhost kernel: 72 03 11 04 00 00 00 0c 00 0a 80 00 00 00 00 00 Mar 18 05:43:04 localhost kernel: 09 c3 05 61 Mar 18 05:43:04 localhost kernel: end_request: I/O error, dev sdc, sector 163775841 Mar 18 05:43:04 localhost kernel: ata2: EH complete Mar 18 05:43:04 localhost kernel: SCSI device sdc: 1953525168 512-byte hdwr sectors (1000205 MB) Mar 18 05:43:11 localhost kernel: sdc: Write Protect is off Mar 18 05:43:12 localhost kernel: SCSI device sdc: drive cache: write back Mar 18 05:44:12 localhost kernel: ata2.01: exception Emask 0x10 SAct 0x0 SErr 0x400100 action 0x6 frozen Mar 18 05:44:12 localhost kernel: ata2: SError: { UnrecovData Handshk } Mar 18 05:44:12 localhost kernel: ata2.01: cmd 35/00:00:3f:05:c3/00:04:09:00:00/f0 tag 0 dma 524288 out Mar 18 05:44:12 localhost kernel: res 40/00:cf:61:05:c3/40:03:09:00:00/f0 Emask 0x14 (ATA bus error) Mar 18 05:44:12 localhost kernel: ata2.01: status: { DRDY } 169,51 34% Mar 18 05:44:23 localhost kernel: ata2: hard resetting link Mar 18 05:44:24 localhost kernel: ata2: SATA link up 3.0 Gbps (SStatus 123 SControl 300) Mar 18 05:44:24 localhost kernel: ata2.01: revalidation failed (errno=-2) Mar 18 05:44:24 localhost kernel: ata2.01: disabled Mar 18 05:44:25 localhost kernel: ata2.00: failed to IDENTIFY (I/O error, err_mask=0x40) Mar 18 05:44:25 localhost kernel: ata2.00: revalidation failed (errno=-5) Mar 18 05:44:25 localhost kernel: ata2: failed to recover some devices, retrying in 5 secs Mar 18 05:44:30 localhost kernel: ata2: hard resetting link Mar 18 05:44:30 localhost kernel: ata2: SATA link up 3.0 Gbps (SStatus 123 SControl 300) Mar 18 05:44:30 localhost kernel: ata2.00: configured for UDMA/133 Mar 18 05:44:30 localhost kernel: ata2: EH complete
以下らへんを参考に復旧作業中だがだめだったらディスク買い換えるか、、、、
CentOSでソフトウェアRAIDの構築
smartd での sector error 復活作業
ext3でフォーマットする方法
HDDの不良ブロックをどうにかできないか – ubuntu badblocks mke2fs e2fsck
【追記】
badblocksコマンドで/dev/sdcのディスクについて不良セクタのチェックを行ったが特に検出されなかった(1TBのディスクなので--fullオプションをつけて実行したら一週間ぐらいかかった)
とりあえずRAID1を構築しなおして/dev/md0のRAIDデバイスについてext3でフォーマットしなおしたら復旧した。
ソフトウェアRAIDの書き込み失敗とかそういう論理的な問題だったのだろうか、、、、
Pythonによる並列プログラミング -GPGPUも-
pythonでの並列プログラミングの勉強した結果を載せてみます。
pycudaというCUDAのpythonバインディングも試してみました。
single_thread_execute.py
import numpy import time size = 256 arr_0 = numpy.arange(size*size) arr_1 = numpy.arange(size*size) arr_result = numpy.zeros(size*size) print "execute start" start = time.time() count = 0 for i in range(size): for j in range(size): tmp = 0 for k in range(size): row = k + (i*size) col = j + (k*size) tmp += arr_0[row] * arr_1[col] arr_result[j + (i*size)] = tmp #print "i = " + str(i) print "time = " + str((time.time() - start)) #print arr_result.sum() result_sum = 0 for i in arr_result: result_sum += i print result_sum
multi_thread_execute.py
import numpy import threading import time size = 256 arr_0 = numpy.arange(size*size) arr_1 = numpy.arange(size*size) arr_result = numpy.zeros(size*size) task_complete = 0 class task(threading.Thread): def __init__(self, i): threading.Thread.__init__(self) self.i = i def run(self): global task_complete global size global arr_0 global arr_1 global arr_result i = self.i for j in range(size): tmp = 0 for k in range(size): row = k + (i*size) col = j + (k*size) tmp += arr_0[row] * arr_1[col] arr_result[j + (i*size)] = tmp task_complete += 1 #print "i = " + str(i) print "execute start" start = time.time() count = 0 thread_arr = [] print "task init" for i in range(size): thread_arr.append(task(i)) print "start tasks" for i in range(len(thread_arr)): thread_arr[i].start() while True: if(task_complete >= size): break print "done" print "time = " + str((time.time() - start)) #print arr_result.sum() result_sum = 0 for i in arr_result: result_sum += i print result_sum
multi_process_execute.py
import numpy import threading import time from multiprocessing import Process, Value, Array, Lock, Queue size = 256 arr_0 = numpy.arange(size*size) arr_1 = numpy.arange(size*size) def task(q, shared_arr_result): print "start process " while True: if q.empty(): break i = q.get() for j in range(size): tmp = 0 for k in range(size): row = k + (i*size) col = j + (k*size) tmp += arr_0[row] * arr_1[col] shared_arr_result[j + (i*size)] = tmp #print str(i) if __name__ == '__main__': size = 256 q = Queue() for i in range(256): q.put(i) print "execute start" arr_result = numpy.zeros(size*size) shared_arr_result = Array("f", arr_result) process_arr = [0] * 4 print "task init & start" start = time.time() for i in range(len(process_arr)): process_arr[i] = Process(target=task, args=(q, shared_arr_result)) process_arr[i].start() while True: if q.empty(): break print "time = " + str((time.time() - start)) result_sum = 0 for i in shared_arr_result: result_sum += i print result_sum
pycuda_execute.py
import pycuda.autoinit import pycuda.driver as drv import numpy import time from pycuda.compiler import SourceModule mod = SourceModule(""" __global__ void square(int* arr_0, int* arr_1, int* arr_result) { const int size = 256; const int x = blockIdx.x * blockDim.x + threadIdx.x; const int y = blockIdx.y * blockDim.y + threadIdx.y; int tmp = 0; for(int k = 0; k < size; k++) { int row = k + y * size; int col = x + k * size; tmp += arr_0[row] * arr_1[col]; } arr_result[x + y * size] = tmp; } """) size = 128 block = 4 arr_0 = numpy.arange(size*size) arr_1 = numpy.arange(size*size) arr_result = numpy.zeros(size*size) print "start" print arr_result start = time.time() square = mod.get_function("square") square(drv.InOut(arr_0), drv.InOut(arr_1), drv.InOut(arr_result), block=(block, block, 1), grid=(size/block, size/block)) print "end... time = " + str((time.time() - start)) print arr_result
tomcat7とsolr3.5.0のセットアップ(日本語の文字化け対策も)
最新版のsolrとtomcatを準備
apache-tomcat-7.0.23
apache-solr-3.5.0
tomcat7のインストールパスを$TOMCAT
solrのインデックスファイルや設定ファイルを格納するパスを$SOLR_HOMEとする
- solrのWEBアプリケーションを$TOMCAT/webappに配備
$ cp apache-solr-3.5.0/example/webapps/solr.war $TOMCAT/webapps/
- デフォルトの設定ファイルやインデックスファイルなどをコピー
cp -r apache-solr-3.5.0/example/solr/* $SOLR_HOME/ ※apache-solr-3.5.0/exampleはexampleというよりはスケルトンに近い
- ライブラリをコピー
cp -r apache-solr-3.5.0/contrib $SOLR_HOME/ cp -r apache-solr-3.5.0/dist $SOLR_HOME/
- インデックスなどが格納されるデータディレクトリの設定を変更する
vim $SOLR_HOME/solrconfig.xml${solr.data.dir:} ↓${solr.data.dir:$SOLR_HOME/data}
- ライブラリのパスを変更する(相対パスになっているがどこが起点になってるのかよくわからん)
vim $SOLR_HOME/solrconfig.xml↓
↓
↓
JAVA_OPTS="$JAVA_OPTS -Dsolr.home=$SOLR_HOME"
tomcat起動するとhttp://localhost:8080/solr/admin/で管理画面が見えていることを確認
- schema.xmlを設定してみる
<?xml version="1.0" encoding="UTF-8" ?> <schema name="example" version="1.4"> <types> <fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/> <fieldType name="text_cjk" class="solr.TextField" positionIncrementGap="100" > <analyzer> <tokenizer class="solr.CJKTokenizerFactory"/> </analyzer> </fieldType> </types> <fields> <field name="id" type="string" indexed="true" stored="true" required="true" /> <field name="name" type="text_cjk" indexed="true" stored="true" required="true" /> <field name="original_name" type="text_cjk" indexed="true" stored="true" required="true" /> <field name="kana" type="text_cjk" indexed="true" stored="true" required="true" /> <field name="name_en" type="text_cjk" indexed="true" stored="true" required="true" /> </fields> <uniqueKey>id</uniqueKey> <!-- field for the QueryParser to use when an explicit fieldname is absent --> <defaultSearchField>name</defaultSearchField> <!-- SolrQueryParser configuration: defaultOperator="AND|OR" --> <solrQueryParser defaultOperator="OR"/> </schema>
- autocommitをonにする
solr_home/conf/solrconfig.xmlの下記コメントアウトを外す
10000 1000
- このままでは日本語が文字化けして検索にヒットしない問題
tomcatのexampleアプリケーションにSetCharacterEncodingFilter.classがあるのでそれを流用すると方法がネットで出てきた
http://blog.sedays.com/0409/2219_15.php
が、tomcat7にはなぜかSetCharacterEncodingFilter.classがない、、、、
$ ls -la apache-tomcat-7.0.23/webapps/examples/WEB-INF/classes/filters/ ExampleFilter.class ExampleFilter.java
仕方ないのでtomcat6をダウンロードしてきてSetCharacterEncodingFilter.classを手に入れる
mkdir -p $TOMCAT/webapps/solr/WEB-INF/classes/filters cp apache-tomcat-6.0.35/webapps/examples/WEB-INF/classes/filters/SetCharacterEncodingFilter.class .
solrアプリケーションにfilterを設定する
$ vim $TOMCAT/webapps/solr/WEB-INF/web.xml
<filter> <filter-name>Set Character Encoding</filter-name> <filter-class>filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>Set Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
http://kuromame.dip.jp/xoops/modules/pukiwiki/?solr
によると
server.xmlを修正
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" useBodyEncodingForURI="true"/> ←追記
SolrJへのクラスパスを通した上でjythonを起動して以下のように実行
from org.apache.solr.client.solrj.impl import CommonsHttpSolrServer; from org.apache.solr.common import SolrInputDocument server = CommonsHttpSolrServer("http://localhost:8080/solr") doc = SolrInputDocument() doc.addField("id", dic['manageId']) doc.addField("name", dic['artistName']) doc.addField("original_name", dic['artistNameOriginal']) doc.addField("kana", (dic['artistNameKANA'] if (dic.has_key('artistNameKANA')) else "")) doc.addField("name_en", (dic['artistNameEN'] if (dic.has_key('artistNameEN')) else "")) server.add(doc)
Lion + Titanium Mobile1.8.5 + iosSDK5.0での実機転送
開発端末が今まで使っていたMacBookAir(Snow Leopard)からMacBookPro(Lion)にパワーアップしたのでアプリ開発環境も構築し直しなった。
before
MacOS 10.6 Snow Leopard + Titanium Mobile 1.7.3 + XCode4.2(iOS SDK4.3)
after
MacOS 10.7 Lion + Titanium Mobile 1.7.5 + XCode4.2(iOS SDK5.0)
開発しているTitanium Mobileアプリケーションは自作のモジュールをいくつか利用しているので念のため全部再ビルド。
ビルドしたモジュールをアプリケーションに配置してシミュレータで起動したところ問題なく起動しました。
しかし、Titanium Studioから実機に転送しようとすると下記エラーが発生。
[ERROR] Error: Traceback (most recent call last): File "/Library/Application Support/Titanium/mobilesdk/osx/1.6.2/iphone/builder.py", line 1091, in main execute_xcode("iphonesimulator%s" % link_version,["GCC_PREPROCESSOR_DEFINITIONS=__LOG__ID__=%s DEPLOYTYPE=development TI_DEVELOPMENT=1 DEBUG=1 TI_VERSION=%s" % (log_id,sdk_version)],False) File "/Library/Application Support/Titanium/mobilesdk/osx/1.6.2/iphone/builder.py", line 1012, in execute_xcode output = run.run(args,False,False,o) File "/Library/Application Support/Titanium/mobilesdk/osx/1.6.2/iphone/run.py", line 39, in run sys.exit(rc) SystemExit: 65
ビルドするpythonコードを追ってxcodebuildのコマンドを試しに手動で実行するとarmv6がビルドできない的なエラーが出てました。
とりあえず以前の環境のMacBookAirで再度ビルドをためしてみると
MBA + Ti SDK1.7.3 + ios SDK4.3 OK
MBA + Ti SDK1.7.5 + ios SDK4.3 OK
MBP + Ti SDK1.7.5 + ios SDK5.0 NG
の切り分けになった。
どうやらios sdk5.0が怪しい。
iOS SDK4.3を試したいがためにMacBookProのほうでxcode4.2をアンインストールして、xcode3.2をインストールしてから、xcode4.2を上書きインストールしてみるも状況変わらず。
泣きそうになりながらネットを調べていると状況的には同じ質問があるが、最新のTitaniumMobileではiOS5.0対応していると記載がある。。。
http://developer.appcelerator.com/question/120631/ios-5
さらに泣きそうになりながらネットを調べているとどうやらxcode4.2にアップグレードすると色々設定が変わってしまう的な記事を発見。
http://ishidak.blogspot.com/2011/10/xcode-42-upgrade-problem-solution.html
書いてある通りにarmv6を設定
これを全モジュールに設定してビルドしなおしてからアプリケーションに組み込めば問題なく動きました。
ちなみにMacを乗り換えたタイミングでユーザーが管理者ユーザーではなくなったせいなのかTitanium SDKのインストール先が/Library/Application\ Support/Titaniumから~/Library/Application\ Support/Titaniumになっていたので、各モジュールのTITANIUM_SDKのパスを~/Library/Application\ Support/Titaniumに変更してあります。
この問題のせいで2営業日を無駄にした、、、
自宅サーバのcuda環境を3.2→4.0にバージョンアップ
基本的にはドキュメントに書いてある通りセットアップすればOK
http://developer.nvidia.com/cuda-toolkit-40
自宅サーバのOSはCentOS 5.6。
私は雰囲気でインストールしてたらこんなエラーが出るようになってしまった。
$ ./deviceQuery [deviceQuery] starting... ./deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) cudaGetDeviceCount returned 38 -> no CUDA-capable device is detected [deviceQuery] test results... FAILED Press ENTER to exit...
ドキュメントのpdfを見たらGUIを使っていない場合は/dev/nvidia*のデバイスファイルを手動で確保しないといけないらしくドキュメントに記載されているシェルを実行する必要があったみたいだ。
#!/bin/bash /sbin/modprobe nvidia if [ "$?" -eq 0 ]; then # Count the number of NVIDIA controllers found. NVDEVS=`lspci | grep -i NVIDIA` N3D=`echo "$NVDEVS" | grep "3D controller" | wc -l` NVGA=`echo "$NVDEVS" | grep "VGA compatible controller" | wc -l` N=`expr $N3D + $NVGA - 1` for i in `seq 0 $N`; do mknod -m 666 /dev/nvidia$i c 195 $i done mknod -m 666 /dev/nvidiactl c 195 255 else exit 1 fi
これでdeviceQuery実行したらちゃんと起動できました。
にして、これ電源入れ直すたびに実行しないといけないっぽい、、、、
最近は節電のために自宅サーバは日中は電源切っているので、忘れないようにしないと、、、