20200414のLinuxに関する記事は7件です。

自作PCにUbuntu 18.04 LSTをインストール & セットアップ (NVIDIAドライバ関係)

?本記事の概要
自作PCにUbuntu 18.04.04 LSTをインストールした際の手順を残しておきます。
以下目次ですが,全部まとめると長くなりそうなので今回は太字までとします。

# マシン構成について
Ubuntu 18.04.4 LSTのインストール
NVIDIAドライバ & CUDAの更新 (ログインループ改善)
← ここまで
fcitx-mozcのインストール & 設定
XKBによるキーマップ変更 (for HHKB [US])
# 適宜追記

マシン構成について

今回Ubuntu 18.04.04 LSTをインストールしたマシンの構成は以下の通りです。

構成要素 購入パーツ名
マザーボード X570 Taichi (BIOS ver. 2.70; ASRock)
CPU Ryzen 7 3700X (AMD)
CPUクーラー 虎徹 Mark II (サイズ)
グラフィックボード GeForce RTX 2080 Ti VENTUS GP OC (MSI)
メモリ DDR4-3200 16 GB×2 (Crucial)
SSD (OSインストール先) MX500 500 GB 2.5インチ (Crucial)
HDD (データ保存用) WD Red 3 TB 3.5インチ (Western Degital)
電源 RM850x 850 W (80PLUS GOLD; Corsair)
ケース Define C (Fractal Design)

Ubuntu 18.04.4 LSTのインストール

事前情報として,Zen 2アーキテクチャを採用した第三世代RyzenにはRDRAND関係に不具合があり,Ubuntu等がすんなりとインストールできないらしいぞ,という話を耳にしていました。

が,ビクビクしながらインストールを試みたところ,特になんの障害もなくインストールに成功しました (BIOSがアップデートされた? Ubuntuにパッチが当たった?)。

ちなみにOSインストールに使用したUSBメモリスティックは,下記の記事を参考に準備しました。
『MacでUbuntu 18.04のインストールUSBメモリスティックの作成』

NVIDIAドライバ & CUDAの更新

「特になんの障害もなくインストールできました」と書きましたが,実はインストール後に再起動してログインする際に問題が発生。

パスワードを入力してログインしようとするも,画面暗転後にログイン画面に戻されてしまいました (ログインループ)。

調べてみたところ同様のトラブルに見舞われた方も多く,どうやらインストールの際に古いver.のNVIDIAドライバーが適応されることが原因のようでした。

そこで解決策として,GUIを介さず仮想コンソールからログインし,新しいver.のNVIDIAドライバーをインストールしなおしました。
以下,その手順です。

ログイン画面でControl + Alt + Fn2を押すことで仮想コンソールに入りログインします。ログインできたら,とりあえずapt updateapt upgradeしておきます。

$ sudo apt update
$ sudo apt upgrade

次に,現在インストールされているNVIDIAドライバーおよびCUDAをアンインストールします。

$ sudo apt --purge remove nvidia-*
$ sudo apt --purge remove cuda-*

ここで,現在aptでインストールできるドライバを検索してみます。

$ apt list nvidia-driver-*

すると僕の環境では次のように表示されました (...以降は省略)。

nvidia-driver-390/...
nvidia-driver-418/...
nvidia-driver-430/...
nvidia-driver-435/...

NVIDIAドライバダウンロードのページで検索すると,本記事作成時ではver. 440が推奨されるのですが,とりあえずnvidia-driver-435をインストールして再起動します (後からもう一度インストールしなおします)。

$ sudo apt install nvidia-driver-435
$ sudo reboot

再起動後,無事にGUIからログインすることができました。

もし日本語版のUbuntuをインストールした場合は,ホームディレクトリの中身 (DesktopDocuments,etc...) が日本語になっていて不便なので,この時点で下記コマンドから設定を変更します。

$ LANG=C xdg-user-dirs-gtk-update

次に,NVIDIA推奨ドライバであるver. 440CUDAをインストールします。

まず,CUDA ToolkitのページからDownload Nowをクリックし,CUDA Toolkit (本記事作成時ではver. 10.2) のダウンロードページを開きます。

Operating System:Linux
Architecture:x86_64
Distribution:Ubuntu
Version:18.04
Installer Type:deb (network)
のように選択することで,表示されるインストールガイドに従い下記のコマンドを実行します (変更される可能性があるのでコピペ厳禁)。

$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
$ sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
$ sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
$ sudo add-apt-repository "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /"
$ sudo apt update

これでCUDAリポジトリが追加され,最新ver.のNVIDIAドライバapt経由でインストールできるようになります。

$ apt list nvidia-driver-*

nvidia-driver-440がリストに入っていることを確認したら,さきほど仮でインストールしたnvidia-driver-435をアンインストールし,nvidia-driver-440をインストールしてから再起動します。

$ sudo apt --purge remove nvidia-*
$ sudo apt --purge remove cuda-*
$ sudo apt install nvidia-driver-440

再起動したら念のため (?) apt updateapt upgradeしておきました (不要かも)。次にCUDAもインストールしておきます。

$ sudo apt install cuda

nvidia-smiコマンドで目的のNVIDIAドライバおよびCUDAがインストールされたことを確認します。

$ nvidia-smi
Tue Apr 14 22:34:12 2020       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.64.00    Driver Version: 440.64.00    CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce RTX 208...  On   | 00000000:0C:00.0  On |                  N/A |
| 22%   32C    P8    20W / 260W |    552MiB / 11011MiB |      1%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      1169      G   /usr/lib/xorg/Xorg                            18MiB |
|    0      1200      G   /usr/bin/gnome-shell                          57MiB |
|    0      1485      G   /usr/lib/xorg/Xorg                           163MiB |
|    0      1617      G   /usr/bin/gnome-shell                         171MiB |
|    0      2836      G   ...AAAAAAAAAAAACAAAAAAAAAA= --shared-files   131MiB |
|    0      4479      G   gnome-control-center                           6MiB |
+-----------------------------------------------------------------------------+

これにて完了です (CUDA関係のPATH設定は別途必要)。

次回以降は個別のセットアップ (例えばキーマップ変更など) で詰まったところをメモしていこうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プロジェクトをMavenでビルドできない時の対応方法

  • 環境
    • CentOS Linux release 7.6.1810 (Core)
    • Apache Maven 3.2.5
    • Java1.8.0_242 と Java1.6.0_41

事象1 : Unknown host static.appfuse.org

$ mvn install -Dmaven.test.skip=true
...省略...
[ERROR] Failed to execute goal on project ... Could not transfer artifact jsonic:jsonic:pom:1.2.0 from/to appfuse (http://static.appfuse.org/repository): static.appfuse.org: Name or service not known: Unknown host static.appfuse.org: Name or service not known -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

原因 : リポジトリがもうない

http://static.appfuse.org/repository はなくなったようだ・・・あったことも知らなかったけど

対応方法 : pom.xmlのリポジトリ設定を削除する

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
...省略...
  <repositories>
...↓削除↓...
    <repository>
      <id>appfuse</id>
      <url>http://static.appfuse.org/repository</url>
    </repository>
...↑削除↑...
    <repository>
      <id>central</id>
      <url>http://repo1.maven.org/maven2</url>
    </repository>
...省略...

事象2 : Return code is: 501, ReasonPhrase: HTTPS Required.

事象1のエラーで-eオプションを知った。

To see the full stack trace of the errors, re-run Maven with the -e switch.

$ mvn install -Dmaven.test.skip=true -e
...省略...
Caused by: org.apache.maven.wagon.TransferFailedException: Failed to transfer file: http://repo1.maven.org/maven2/junit/junit/4.7/junit-4.7.pom. Return code is: 501, ReasonPhrase: HTTPS Required.
    at org.apache.maven.wagon.providers.http.AbstractHttpClientWagon.resourceExists(AbstractHttpClientWagon.java:740)
    at org.apache.maven.wagon.providers.http.AbstractHttpClientWagon.resourceExists(AbstractHttpClientWagon.java:696)
    at org.eclipse.aether.transport.wagon.WagonTransporter$PeekTaskRunner.run(WagonTransporter.java:518)
    at org.eclipse.aether.transport.wagon.WagonTransporter.execute(WagonTransporter.java:427)
    at org.eclipse.aether.transport.wagon.WagonTransporter.peek(WagonTransporter.java:398)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$PeekTaskRunner.runTask(BasicRepositoryConnector.java:376)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run(BasicRepositoryConnector.java:350)
    ... 40 more
[ERROR] 
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

原因 : repo.maven.apache.org/maven2/ではHTTPが使えなくなったから

Central 501 HTTPS Required – Sonatype Support

対応 : pom.xmlのリポジトリ設定をHTTPSに変更する

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
...省略...
  <repositories>
    <repository>
      <id>central</id>
      <url>https://repo1.maven.org/maven2</url>
    </repository>
...省略...

事象3 : SSLException: Received fatal alert: protocol_version

$ mvn install -Dmaven.test.skip=true -e
Caused by: javax.net.ssl.SSLException: Received fatal alert: protocol_version
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1902)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1074)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1320)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1347)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1331)
    at org.apache.maven.wagon.providers.http.httpclient.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275)
    at org.apache.maven.wagon.providers.http.httpclient.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:254)
    at org.apache.maven.wagon.providers.http.httpclient.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:123)
    at org.apache.maven.wagon.providers.http.httpclient.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:318)
    at org.apache.maven.wagon.providers.http.httpclient.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
    at org.apache.maven.wagon.providers.http.httpclient.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
    at org.apache.maven.wagon.providers.http.httpclient.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
    at org.apache.maven.wagon.providers.http.httpclient.impl.execchain.RetryExec.execute(RetryExec.java:86)
    at org.apache.maven.wagon.providers.http.httpclient.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    at org.apache.maven.wagon.providers.http.httpclient.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.maven.wagon.providers.http.httpclient.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.maven.wagon.providers.http.AbstractHttpClientWagon.execute(AbstractHttpClientWagon.java:848)
    at org.apache.maven.wagon.providers.http.AbstractHttpClientWagon.resourceExists(AbstractHttpClientWagon.java:708)
    ... 46 more
[ERROR] 
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

原因 : repo.maven.apache.org/maven2/ではTLSv1.0とTLSv1.1は使えないから

JDK8はデフォルトでTLSv1.2になるらしいが・・・プロジェクトはJDK6だからTLS v1.1になってしまったのかしら?
Diagnosing TLS, SSL, and HTTPS | Oracle Java Platform Group, Product Management Blog

対応方法 : -Dhttps.protocols=TLSv1.2を指定する

Java7 環境で maven が失敗する (Received fatal alert: protocol_version) - Qiita

$ mvn install -Dmaven.test.skip=true -e -Dhttps.protocols=TLSv1.2
...省略...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.980 s
[INFO] Finished at: 2020-04-14T21:34:21+09:00
[INFO] Final Memory: 22M/962M
[INFO] ------------------------------------------------------------------------

事象4 : Could not transfer artifact jsonic:jsonic:pom:1.2.0 from/to central

$ mvn install -Dmaven.test.skip=true -e
...省略...
Caused by: org.eclipse.aether.transfer.ArtifactTransferException: Could not transfer artifact jsonic:jsonic:pom:1.2.0 from/to central (https://repo1.maven.org/maven2): Received fatal alert: protocol_version
    at org.eclipse.aether.connector.basic.ArtifactTransportListener.transferFailed(ArtifactTransportListener.java:43)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run(BasicRepositoryConnector.java:355)
    at org.eclipse.aether.util.concurrency.RunnableErrorForwarder$1.run(RunnableErrorForwarder.java:67)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$DirectExecutor.execute(BasicRepositoryConnector.java:581)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector.get(BasicRepositoryConnector.java:249)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.performDownloads(DefaultArtifactResolver.java:520)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:421)
    ... 35 more
Caused by: org.apache.maven.wagon.TransferFailedException: Received fatal alert: protocol_version
    at org.apache.maven.wagon.providers.http.AbstractHttpClientWagon.fillInputData(AbstractHttpClientWagon.java:1085)
    at org.apache.maven.wagon.providers.http.AbstractHttpClientWagon.fillInputData(AbstractHttpClientWagon.java:977)
    at org.apache.maven.wagon.StreamWagon.getInputStream(StreamWagon.java:116)
    at org.apache.maven.wagon.StreamWagon.getIfNewer(StreamWagon.java:88)
    at org.apache.maven.wagon.StreamWagon.get(StreamWagon.java:61)
    at org.eclipse.aether.transport.wagon.WagonTransporter$GetTaskRunner.run(WagonTransporter.java:560)
    at org.eclipse.aether.transport.wagon.WagonTransporter.execute(WagonTransporter.java:427)
    at org.eclipse.aether.transport.wagon.WagonTransporter.get(WagonTransporter.java:404)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$GetTaskRunner.runTask(BasicRepositoryConnector.java:447)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run(BasicRepositoryConnector.java:350)
    ... 40 more
Caused by: javax.net.ssl.SSLException: Received fatal alert: protocol_version
...省略...

原因1 : もうCentralポジトリにgroupIdがjsonicjsonicはない

Maven Repository: Search/Browse/Exploreで検索すると・・・ない
image.png

pom.xml
<dependency>
  <groupId>jsonic</groupId>
  <artifactId>jsonic</artifactId>
  <version>1.2.0</version>
</dependency>

対応 : 違うgroupIdとversionのjsonicにする

セントラルリポジトリにはjsonicのバージョン1.2.0がなかったのでバージョンも上げる
image.png

pom.xml
<dependency>
  <groupId>net.arnx</groupId>
  <artifactId>jsonic</artifactId>
  <version>1.2.7</version>
</dependency>

原因2 : .m2ディレクトリの持ち主が自分じゃないから

原因と対応方法は Dockerで作った環境のMavenで/home/path/.m2/repository/x.pom.part.lock (Permission denied)となった時の対応方法 - Qiita

事象5 : Fatal error compiling: 1.8は無効なターゲット・リリースです

maven-compiler-pluginでJava1.8を指定したら怒られた。

$ mvn install -Dmaven.test.skip=true
...省略...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project プロジェクト: Fatal error compiling: 1.8は無効なターゲット・リリースです -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
  <encoding>UTF-8</encoding>
  <source>1.8</source>
  <target>1.8</target>
</configuration>
</plugin>

原因 : 現在のJavaとMavenで使っているJavaのバージョンが違うから

参考 : Maven に JDK 1.8 を認識させる - blog.kymmt.com
Mavenは、JAVA_HOMEがあるとJavaを使うそうです。

# Mavenが使っているのはJava1.6
$ mvn -v
...省略...
Java version: 1.6.0_41, vendor: Sun Microsystems Inc.
Java home: /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.41.x86_64/jre
...省略...

# JAVA_HOMEもJava1.6
$ printenv JAVA_HOME
/usr/lib/jvm/java-1.6.0-openjdk.x86_64

# 使っているのはJava1.8
$ java -version
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)

対応 : JAVA_HOMEを削除してMavenが使うJavaのバージョンを変更する

削除しないでJAVA_HOMEを変更する手段もある。

# JAVA_HOMEを削除して、
$ unset JAVA_HOME

# .bash_profile のJAVA_HOME設定をコメントアウトして
$ vi ~/.bash_profile 
 cat ~/.bash_profile 
...省略...
#JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk.x86_64
#export JAVA_HOME

# 反映すると
$ source ~/.bash_profile 
[1]+  Done                    exec ibus-daemon -dx

# JAVA_HOMEがなくなり、
$ printenv JAVA_HOME
$

# Mavenが使うJavaが、Java1.8になる
$ mvn -v
...省略...
Java version: 1.8.0_242, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre
...省略...

# そうするとエラーが解消する
$ mvn install -Dmaven.test.skip=true
...省略...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.202 s
[INFO] Finished at: 2020-04-15T11:33:39+09:00
[INFO] Final Memory: 18M/749M
[INFO] ------------------------------------------------------------------------

事象6 : was cached in the local repository, resolution will not be reattempted until the update interval of local has elapsed or updates are forced

$ mvn install -Dmaven.test.skip=true -e
...省略...
Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Failure to find ... was cached in the local repository, resolution will not be reattempted until the update interval of local has elapsed or updates are forced
    at org.eclipse.aether.internal.impl.DefaultUpdateCheckManager.newException(DefaultUpdateCheckManager.java:231)
    at org.eclipse.aether.internal.impl.DefaultUpdateCheckManager.checkArtifact(DefaultUpdateCheckManager.java:206)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.gatherDownloads(DefaultArtifactResolver.java:585)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.performDownloads(DefaultArtifactResolver.java:503)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:421)
    ... 40 more
[ERROR] 
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

原因1 : キャッシュ?

[Eclipse]pom.xmlで余計なキャッシュのせいでエラーが発生 | ntの備忘録

対応方法 : .m2/repository/org/apache/mavenディレクトリを削除する

$ rm -rf ~/.m2/repository/org/apache/maven

原因2 : 依存関係にあるプロジェクトのjarがないから

$ mvn install -Dmaven.test.skip=true -e
...省略...
Caused by: org.eclipse.aether.resolution.ArtifactDescriptorException: Failed to read artifact descriptor for jp.co.hoge:hoge-framework-fuga:jar:3.0.0
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom(DefaultArtifactDescriptorReader.java:337)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor(DefaultArtifactDescriptorReader.java:217)
    at org.eclipse.aether.internal.impl.DefaultDependencyCollector.resolveCachedArtifactDescriptor(DefaultDependencyCollector.java:525)
...省略...
Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Failure to find ...was cached in the local repository, resolution will not be reattempted until the update interval of local has elapsed or updates are forced
    at org.eclipse.aether.internal.impl.DefaultUpdateCheckManager.newException(DefaultUpdateCheckManager.java:231)
    at org.eclipse.aether.internal.impl.DefaultUpdateCheckManager.checkArtifact(DefaultUpdateCheckManager.java:206)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.gatherDownloads(DefaultArtifactResolver.java:585)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.performDownloads(DefaultArtifactResolver.java:503)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:421)
    ... 40 more
[ERROR] 
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

対応方法 : 依存関係にあるプロジェクトのjarを作ってからやり直す

STS(eclipse)からmavenビルドでjarファイルを作ろうとしたらエラーになった話 | ヰ刀のおもちゃ箱

今回の場合は、依存関係にあるhoge-framework-fugaプロジェクトのjarを作ってからやり直す

原因3 : リポジトリがないかURLが古い

Eclipseで、プロジェクトを選択 > [Maven] > [Update Project...]したらErrorになった時のこと

[Problems]タブのエラー
Failure to transfer javax.resource:connector:jar:1.0 from http://maven.ow2.org/maven2/ was cached in the local repository, resolution will not be reattempted until the update interval of ow2.org has elapsed or updates are forced. Original error: Could not transfer artifact javax.resource:connector:jar:1.0 from/to ow2.org (http://maven.ow2.org/maven2/): Cannot access http://maven.ow2.org/maven2/ with type legacy using the available connector factories: AetherRepositoryConnectorFactory, BasicRepositoryConnectorFactory
...省略...

Failure to transfer javax.resource:connector:jar:1.0 from http://download.java.net/maven/2/ was cached in the local repository, resolution will not be reattempted until the update interval of java.net has elapsed or updates are forced. Original error: Could not transfer artifact javax.resource:connector:jar:1.0 from/to java.net (http://download.java.net/maven/2/): Cannot access http://download.java.net/maven/2/ with type legacy using the available connector factories: AetherRepositoryConnectorFactory, BasicRepositoryConnectorFactory
...省略...

対応方法 : リポジトリの設定を修正する

  1. エラーになっている http://maven.ow2.org/maven2/ はブラウザでアクセスすると https://repository.ow2.org/nexus/content/repositories/ow2-legacy/ へリダイレクトされるのでリダイレクトされたURLへ変更する
  2. エラーになっている http://download.java.net/maven/2/ はブラウザでアクセスすると We're sorry, the page you requested was not found. となるので削除する
  3. プロジェクトを選択 > [Maven] > [Update Project...]を再度実行
変更前のpom.xml
↓削除↓
<repository>
  <id>java.net</id>
  <url>http://download.java.net/maven/2/</url>
</repository>
↑削除↑
<repository>
  <id>ow2.org</id>
↓URL変更↓
  <url>http://maven.ow2.org/maven2/</url>
</repository>

事象7 : Mavenリポジトリにない独自のjarを指定したらCould not find artifact jp.co.hoge.fuga:hoge-fuga-project:pom

Mavenリポジトリにない独自のjarを指定したら、その親プロジェクトのpomがないと言われた・・・

$ mvn install -Dmaven.test.skip=true -e
Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not find artifact jp.co.hoge.fuga:hoge-fuga-project:pom:2.0.0 in local (file:/home/fuga/hoge-fuga-project/hoge-framework-core/../repo)
    at org.eclipse.aether.connector.basic.ArtifactTransportListener.transferFailed(ArtifactTransportListener.java:39)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run(BasicRepositoryConnector.java:355)
    at org.eclipse.aether.util.concurrency.RunnableErrorForwarder$1.run(RunnableErrorForwarder.java:67)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$DirectExecutor.execute(BasicRepositoryConnector.java:581)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector.get(BasicRepositoryConnector.java:249)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.performDownloads(DefaultArtifactResolver.java:520)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:421)
    ... 40 more
[ERROR] 
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

原因 : 不明

以下サイトの「ローカルリポジトリにインストールする方法その1」みたいなことをやっている。
Mavenリポジトリにないライブラリをpom.xmlで指定する方法 - grep Tips *

対応方法 : pomがないと言われたプロジェクトのpom.xmlをコピーした

Could not find artifact jp.co.hoge.fuga:hoge-fuga-project:pom:2.0.0と言われたので
{ユーザホーム}/.m2/repository/jp/co/hoge/fuga/hoge-fuga-project/pom/2.0.0/ディレクトリ配下に
プロジェクトのpomをhoge-fuga-project-2.0.0.pom(.xmlは不要)にリネームしてコピーしてしのいだ。
ちゃんとした原因と対応方法を知りたい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

業務でよく使うコマンドをまとめてみた

はじめに

業務でログ調査を行うので、その際よく使うコマンドをまとめてみました。

grepコマンド

ファイル中の文字列を検索するコマンドです。

基本的な使い方

grep オプション "検索文字列" ファイル名 

オプション

オプション名 説明
-v 一致しないものを検索する
-e 一致処理に指定した正規表現を使う

cutコマンド

テキストファイルを横方向に分割するコマンドです。

基本的な使い方

必要なバイト数で指定したり、区切り文字でファイルの内容を取得することができます。

cut オプション ファイル名  

オプション

オプション名 説明
-v 区切り文字を指定できる
-e 必要な項目を項目数で指定できる

sortコマンド

データを昇順で並べ替えできるコマンドです。

基本的な使い方

sort ファイル名

uniqコマンド

sortであらかじめ並べ替えされた状態で重複行を削除できるコマンドです。

基本的な使い方

uniq ファイル名

scpコマンド

リモートマシンとローカルマシン、またはリモートマシン間でファイルをコピーする際に使用するコマンドです。

基本的な使い方

scp ユーザ名@リモートのホスト名:コピーしたいリモートのファイル ローカルのコピー先
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Quartus Prime 18.1 で Frame Reader を復活させる

概要

DE10-nano を初めとした Intel SoCFPGA を使って Linux Desktop を表示させたい場合、Frame Buffer をFPGA 側に実装する必要がありますが、最近の Quartus Prime から Frame Reader IP コアが廃止になってしまったため、有償の IP を使わなければなりませんでした。しかし、Quartus Prime Lite/Standard 18.1 に Frame Reader IP コアのソースが残っていましたので、これを Quartus Prime Lite 18.1 でコンパイルする事ができます。

手順

(1) Quartus Prime Lite 18.1 のインストールフォルダから frame_reader フォルダを探します。デフォルトでのインストールなら C:\intelFPGA_lite\18.1\ip\altera の下にあります。

(2) コンパイルしたい Quartus プロジェクトの下にフォルダごとコピーします。ip フォルダとかがあれば、その下でも問題ありません。

(3) <コピーしたフォルダ>\frame_reader\full_ip\frame_reader の中に alt_vip_vfr_hw.tcl と言うファイルがありますので、このファイルの内容を下記のコードに全て置き換えます。

(4) Quartus プロジェクトを開いて、Platform Designer を起動し、IP Catalog に下記のように表示されれば OK です。

pd_ipcatalog.jpg

(5) 既に Frame Reader を実装しているシステムであれば、このまま Generate して再コンパイルすれば 18.1の SOF が完成します。

(6) Frame Reader を実装していないシステムであれば、Frame Reader を Add してパラメタを設定すれば OK です。GUI は昔の Frame Reader と同じです。( Linux Desktop の実装の仕方は必要があれば説明しますが、ここでは詳しくは説明しません)

package require -exact qsys 18.1


# 
# module alt_vip_vfr
# 
set_module_property DESCRIPTION "The Frame Reader Megacore can be used to read a video stream from video frames stored a memory buffer"
set_module_property NAME alt_vip_vfr
set_module_property VERSION 18.1
set_module_property INTERNAL false
set_module_property OPAQUE_ADDRESS_MAP true
set_module_property GROUP test
set_module_property AUTHOR "Intel Corporation"
set_module_property DISPLAY_NAME "Frame Reader"
set_module_property DATASHEET_URL http://www.altera.com/literature/ug/ug_vip.pdf
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
set_module_property EDITABLE true
set_module_property REPORT_TO_TALKBACK false
set_module_property ALLOW_GREYBOX_GENERATION false
set_module_property REPORT_HIERARCHY false


# 
# file sets
# 
add_fileset quartus_synth QUARTUS_SYNTH "" "Quartus Synthesis"
set_fileset_property quartus_synth TOP_LEVEL alt_vipvfr131_vfr
set_fileset_property quartus_synth ENABLE_RELATIVE_INCLUDE_PATHS false
set_fileset_property quartus_synth ENABLE_FILE_OVERWRITE_MODE true
add_fileset_file alt_vipvfr131_vfr.v VERILOG PATH src_hdl/alt_vipvfr131_vfr.v TOP_LEVEL_FILE
add_fileset_file alt_vipvfr131_vfr_controller.v VERILOG PATH src_hdl/alt_vipvfr131_vfr_controller.v
add_fileset_file alt_vipvfr131_vfr_control_packet_encoder.v VERILOG PATH src_hdl/alt_vipvfr131_vfr_control_packet_encoder.v
add_fileset_file alt_vipvfr131_prc.v VERILOG PATH src_hdl/alt_vipvfr131_prc.v
add_fileset_file alt_vipvfr131_prc_core.v VERILOG PATH src_hdl/alt_vipvfr131_prc_core.v
add_fileset_file alt_vipvfr131_prc_read_master.v VERILOG PATH src_hdl/alt_vipvfr131_prc_read_master.v
add_fileset_file alt_vipvfr131_common_package.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_package.vhd
add_fileset_file alt_vipvfr131_common_avalon_mm_bursting_master_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_avalon_mm_bursting_master_fifo.vhd
add_fileset_file alt_vipvfr131_common_avalon_mm_master.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_avalon_mm_master.v
add_fileset_file alt_vipvfr131_common_unpack_data.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_unpack_data.v
add_fileset_file alt_vipvfr131_common_avalon_mm_slave.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_avalon_mm_slave.v
add_fileset_file alt_vipvfr131_common_stream_output.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_stream_output.v
add_fileset_file alt_vipvfr131_common_pulling_width_adapter.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_pulling_width_adapter.vhd
add_fileset_file alt_vipvfr131_common_general_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_general_fifo.vhd
add_fileset_file alt_vipvfr131_common_fifo_usedw_calculator.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_fifo_usedw_calculator.vhd
add_fileset_file alt_vipvfr131_common_gray_clock_crosser.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_gray_clock_crosser.vhd
add_fileset_file alt_vipvfr131_common_std_logic_vector_delay.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_std_logic_vector_delay.vhd
add_fileset_file alt_vipvfr131_common_one_bit_delay.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_one_bit_delay.vhd
add_fileset_file alt_vipvfr131_common_logic_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_logic_fifo.vhd
add_fileset_file alt_vipvfr131_common_ram_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_ram_fifo.vhd
add_fileset_file alt_vipvfr131_vfr.sdc SDC PATH alt_vipvfr131_vfr.sdc

add_fileset sim_verilog SIM_VERILOG "" "Verilog Simulation"
set_fileset_property sim_verilog TOP_LEVEL alt_vipvfr131_vfr
set_fileset_property sim_verilog ENABLE_RELATIVE_INCLUDE_PATHS false
set_fileset_property sim_verilog ENABLE_FILE_OVERWRITE_MODE true
add_fileset_file alt_vipvfr131_vfr.v VERILOG PATH src_hdl/alt_vipvfr131_vfr.v
add_fileset_file alt_vipvfr131_vfr_controller.v VERILOG PATH src_hdl/alt_vipvfr131_vfr_controller.v
add_fileset_file alt_vipvfr131_vfr_control_packet_encoder.v VERILOG PATH src_hdl/alt_vipvfr131_vfr_control_packet_encoder.v
add_fileset_file alt_vipvfr131_prc.v VERILOG PATH src_hdl/alt_vipvfr131_prc.v
add_fileset_file alt_vipvfr131_prc_core.v VERILOG PATH src_hdl/alt_vipvfr131_prc_core.v
add_fileset_file alt_vipvfr131_prc_read_master.v VERILOG PATH src_hdl/alt_vipvfr131_prc_read_master.v
add_fileset_file alt_vipvfr131_common_package.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_package.vhd
add_fileset_file alt_vipvfr131_common_avalon_mm_bursting_master_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_avalon_mm_bursting_master_fifo.vhd
add_fileset_file alt_vipvfr131_common_avalon_mm_master.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_avalon_mm_master.v
add_fileset_file alt_vipvfr131_common_unpack_data.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_unpack_data.v
add_fileset_file alt_vipvfr131_common_avalon_mm_slave.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_avalon_mm_slave.v
add_fileset_file alt_vipvfr131_common_stream_output.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_stream_output.v
add_fileset_file alt_vipvfr131_common_pulling_width_adapter.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_pulling_width_adapter.vhd
add_fileset_file alt_vipvfr131_common_general_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_general_fifo.vhd
add_fileset_file alt_vipvfr131_common_fifo_usedw_calculator.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_fifo_usedw_calculator.vhd
add_fileset_file alt_vipvfr131_common_gray_clock_crosser.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_gray_clock_crosser.vhd
add_fileset_file alt_vipvfr131_common_std_logic_vector_delay.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_std_logic_vector_delay.vhd
add_fileset_file alt_vipvfr131_common_one_bit_delay.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_one_bit_delay.vhd
add_fileset_file alt_vipvfr131_common_logic_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_logic_fifo.vhd
add_fileset_file alt_vipvfr131_common_ram_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_ram_fifo.vhd
add_fileset_file alt_vipvfr131_vfr.sdc SDC PATH alt_vipvfr131_vfr.sdc

add_fileset sim_vhdl SIM_VHDL "" "VHDL Simulation"
set_fileset_property sim_vhdl TOP_LEVEL alt_vipvfr131_vfr
set_fileset_property sim_vhdl ENABLE_RELATIVE_INCLUDE_PATHS false
set_fileset_property sim_vhdl ENABLE_FILE_OVERWRITE_MODE true
add_fileset_file alt_vipvfr131_vfr.v VERILOG PATH src_hdl/alt_vipvfr131_vfr.v
add_fileset_file alt_vipvfr131_vfr_controller.v VERILOG PATH src_hdl/alt_vipvfr131_vfr_controller.v
add_fileset_file alt_vipvfr131_vfr_control_packet_encoder.v VERILOG PATH src_hdl/alt_vipvfr131_vfr_control_packet_encoder.v
add_fileset_file alt_vipvfr131_prc.v VERILOG PATH src_hdl/alt_vipvfr131_prc.v
add_fileset_file alt_vipvfr131_prc_core.v VERILOG PATH src_hdl/alt_vipvfr131_prc_core.v
add_fileset_file alt_vipvfr131_prc_read_master.v VERILOG PATH src_hdl/alt_vipvfr131_prc_read_master.v
add_fileset_file alt_vipvfr131_common_package.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_package.vhd
add_fileset_file alt_vipvfr131_common_avalon_mm_bursting_master_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_avalon_mm_bursting_master_fifo.vhd
add_fileset_file alt_vipvfr131_common_avalon_mm_master.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_avalon_mm_master.v
add_fileset_file alt_vipvfr131_common_unpack_data.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_unpack_data.v
add_fileset_file alt_vipvfr131_common_avalon_mm_slave.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_avalon_mm_slave.v
add_fileset_file alt_vipvfr131_common_stream_output.v VERILOG PATH ../../common_hdl/alt_vipvfr131_common_stream_output.v
add_fileset_file alt_vipvfr131_common_pulling_width_adapter.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_pulling_width_adapter.vhd
add_fileset_file alt_vipvfr131_common_general_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_general_fifo.vhd
add_fileset_file alt_vipvfr131_common_fifo_usedw_calculator.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_fifo_usedw_calculator.vhd
add_fileset_file alt_vipvfr131_common_gray_clock_crosser.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_gray_clock_crosser.vhd
add_fileset_file alt_vipvfr131_common_std_logic_vector_delay.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_std_logic_vector_delay.vhd
add_fileset_file alt_vipvfr131_common_one_bit_delay.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_one_bit_delay.vhd
add_fileset_file alt_vipvfr131_common_logic_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_logic_fifo.vhd
add_fileset_file alt_vipvfr131_common_ram_fifo.vhd VHDL PATH ../../common_hdl/alt_vipvfr131_common_ram_fifo.vhd


# 
# documentation links
# 
add_documentation_link "Data Sheet" http://www.altera.com/literature/ug/ug_vip.pdf
add_documentation_link "Data Sheet" http://www.altera.com/literature/ug/ug_vip.pdf


# 
# parameters
# 
add_parameter FAMILY STRING "Cyclone IV" "Current device family selected"
set_parameter_property FAMILY DEFAULT_VALUE "Cyclone IV"
set_parameter_property FAMILY DISPLAY_NAME "Device family selected"
set_parameter_property FAMILY TYPE STRING
set_parameter_property FAMILY VISIBLE false
set_parameter_property FAMILY UNITS None
set_parameter_property FAMILY DESCRIPTION "Current device family selected"
set_parameter_property FAMILY AFFECTS_GENERATION false
set_parameter_property FAMILY SYSTEM_INFO_TYPE DEVICE_FAMILY
add_parameter BITS_PER_PIXEL_PER_COLOR_PLANE INTEGER 8 "The number of bits used per pixel, per color plane"
set_parameter_property BITS_PER_PIXEL_PER_COLOR_PLANE DEFAULT_VALUE 8
set_parameter_property BITS_PER_PIXEL_PER_COLOR_PLANE DISPLAY_NAME "Bits per pixel per color plane"
set_parameter_property BITS_PER_PIXEL_PER_COLOR_PLANE TYPE INTEGER
set_parameter_property BITS_PER_PIXEL_PER_COLOR_PLANE UNITS None
set_parameter_property BITS_PER_PIXEL_PER_COLOR_PLANE ALLOWED_RANGES 4:16
set_parameter_property BITS_PER_PIXEL_PER_COLOR_PLANE DESCRIPTION "The number of bits used per pixel, per color plane"
set_parameter_property BITS_PER_PIXEL_PER_COLOR_PLANE AFFECTS_GENERATION false
set_parameter_property BITS_PER_PIXEL_PER_COLOR_PLANE HDL_PARAMETER true
add_parameter NUMBER_OF_CHANNELS_IN_PARALLEL INTEGER 3 "The number color planes transmitted in parallel"
set_parameter_property NUMBER_OF_CHANNELS_IN_PARALLEL DEFAULT_VALUE 3
set_parameter_property NUMBER_OF_CHANNELS_IN_PARALLEL DISPLAY_NAME "Number of color planes in parallel"
set_parameter_property NUMBER_OF_CHANNELS_IN_PARALLEL TYPE INTEGER
set_parameter_property NUMBER_OF_CHANNELS_IN_PARALLEL UNITS None
set_parameter_property NUMBER_OF_CHANNELS_IN_PARALLEL ALLOWED_RANGES 1:4
set_parameter_property NUMBER_OF_CHANNELS_IN_PARALLEL DESCRIPTION "The number color planes transmitted in parallel"
set_parameter_property NUMBER_OF_CHANNELS_IN_PARALLEL AFFECTS_GENERATION false
set_parameter_property NUMBER_OF_CHANNELS_IN_PARALLEL HDL_PARAMETER true
add_parameter NUMBER_OF_CHANNELS_IN_SEQUENCE INTEGER 1 "The number color planes transmitted in sequence"
set_parameter_property NUMBER_OF_CHANNELS_IN_SEQUENCE DEFAULT_VALUE 1
set_parameter_property NUMBER_OF_CHANNELS_IN_SEQUENCE DISPLAY_NAME "Number of color planes in sequence"
set_parameter_property NUMBER_OF_CHANNELS_IN_SEQUENCE TYPE INTEGER
set_parameter_property NUMBER_OF_CHANNELS_IN_SEQUENCE UNITS None
set_parameter_property NUMBER_OF_CHANNELS_IN_SEQUENCE ALLOWED_RANGES 1:3
set_parameter_property NUMBER_OF_CHANNELS_IN_SEQUENCE DESCRIPTION "The number color planes transmitted in sequence"
set_parameter_property NUMBER_OF_CHANNELS_IN_SEQUENCE AFFECTS_GENERATION false
set_parameter_property NUMBER_OF_CHANNELS_IN_SEQUENCE HDL_PARAMETER true
add_parameter MAX_IMAGE_WIDTH INTEGER 640 "The maximum width of images / video frames"
set_parameter_property MAX_IMAGE_WIDTH DEFAULT_VALUE 640
set_parameter_property MAX_IMAGE_WIDTH DISPLAY_NAME "Maximum Image width"
set_parameter_property MAX_IMAGE_WIDTH TYPE INTEGER
set_parameter_property MAX_IMAGE_WIDTH UNITS None
set_parameter_property MAX_IMAGE_WIDTH ALLOWED_RANGES 32:2600
set_parameter_property MAX_IMAGE_WIDTH DESCRIPTION "The maximum width of images / video frames"
set_parameter_property MAX_IMAGE_WIDTH AFFECTS_GENERATION false
set_parameter_property MAX_IMAGE_WIDTH HDL_PARAMETER true
add_parameter MAX_IMAGE_HEIGHT INTEGER 480 "The maximum height of images / video frames"
set_parameter_property MAX_IMAGE_HEIGHT DEFAULT_VALUE 480
set_parameter_property MAX_IMAGE_HEIGHT DISPLAY_NAME "Maximum Image height"
set_parameter_property MAX_IMAGE_HEIGHT TYPE INTEGER
set_parameter_property MAX_IMAGE_HEIGHT UNITS None
set_parameter_property MAX_IMAGE_HEIGHT ALLOWED_RANGES 32:2600
set_parameter_property MAX_IMAGE_HEIGHT DESCRIPTION "The maximum height of images / video frames"
set_parameter_property MAX_IMAGE_HEIGHT AFFECTS_GENERATION false
set_parameter_property MAX_IMAGE_HEIGHT HDL_PARAMETER true
add_parameter MEM_PORT_WIDTH INTEGER 256 "The width in bits of the master port"
set_parameter_property MEM_PORT_WIDTH DEFAULT_VALUE 256
set_parameter_property MEM_PORT_WIDTH DISPLAY_NAME "Master port width"
set_parameter_property MEM_PORT_WIDTH TYPE INTEGER
set_parameter_property MEM_PORT_WIDTH UNITS None
set_parameter_property MEM_PORT_WIDTH ALLOWED_RANGES 16:256
set_parameter_property MEM_PORT_WIDTH DESCRIPTION "The width in bits of the master port"
set_parameter_property MEM_PORT_WIDTH AFFECTS_GENERATION false
set_parameter_property MEM_PORT_WIDTH HDL_PARAMETER true
add_parameter RMASTER_FIFO_DEPTH INTEGER 64 "The depth of the read master FIFO"
set_parameter_property RMASTER_FIFO_DEPTH DEFAULT_VALUE 64
set_parameter_property RMASTER_FIFO_DEPTH DISPLAY_NAME "Read master FIFO depth"
set_parameter_property RMASTER_FIFO_DEPTH TYPE INTEGER
set_parameter_property RMASTER_FIFO_DEPTH UNITS None
set_parameter_property RMASTER_FIFO_DEPTH ALLOWED_RANGES 8:1024
set_parameter_property RMASTER_FIFO_DEPTH DESCRIPTION "The depth of the read master FIFO"
set_parameter_property RMASTER_FIFO_DEPTH AFFECTS_GENERATION false
set_parameter_property RMASTER_FIFO_DEPTH HDL_PARAMETER true
add_parameter RMASTER_BURST_TARGET INTEGER 32 "The target burst size of the read master"
set_parameter_property RMASTER_BURST_TARGET DEFAULT_VALUE 32
set_parameter_property RMASTER_BURST_TARGET DISPLAY_NAME "Read master FIFO burst target"
set_parameter_property RMASTER_BURST_TARGET TYPE INTEGER
set_parameter_property RMASTER_BURST_TARGET UNITS None
set_parameter_property RMASTER_BURST_TARGET ALLOWED_RANGES 2:256
set_parameter_property RMASTER_BURST_TARGET DESCRIPTION "The target burst size of the read master"
set_parameter_property RMASTER_BURST_TARGET AFFECTS_GENERATION false
set_parameter_property RMASTER_BURST_TARGET HDL_PARAMETER true
add_parameter CLOCKS_ARE_SEPARATE INTEGER 1 "Use separate clock for the Avalon-MM master interface"
set_parameter_property CLOCKS_ARE_SEPARATE DEFAULT_VALUE 1
set_parameter_property CLOCKS_ARE_SEPARATE DISPLAY_NAME "Use separate clock for the Avalon-MM master interface"
set_parameter_property CLOCKS_ARE_SEPARATE TYPE INTEGER
set_parameter_property CLOCKS_ARE_SEPARATE UNITS None
set_parameter_property CLOCKS_ARE_SEPARATE ALLOWED_RANGES 0:1
set_parameter_property CLOCKS_ARE_SEPARATE DESCRIPTION "Use separate clock for the Avalon-MM master interface"
set_parameter_property CLOCKS_ARE_SEPARATE DISPLAY_HINT boolean
set_parameter_property CLOCKS_ARE_SEPARATE AFFECTS_GENERATION false
set_parameter_property CLOCKS_ARE_SEPARATE HDL_PARAMETER true


# 
# display items
# 


# 
# connection point clock_reset
# 
add_interface clock_reset clock end
set_interface_property clock_reset clockRate 0
set_interface_property clock_reset ENABLED true
set_interface_property clock_reset EXPORT_OF ""
set_interface_property clock_reset PORT_NAME_MAP ""
set_interface_property clock_reset CMSIS_SVD_VARIABLES ""
set_interface_property clock_reset SVD_ADDRESS_GROUP ""

add_interface_port clock_reset clock clk Input 1


# 
# connection point clock_reset_reset
# 
add_interface clock_reset_reset reset end
set_interface_property clock_reset_reset associatedClock clock_reset
set_interface_property clock_reset_reset synchronousEdges DEASSERT
set_interface_property clock_reset_reset ENABLED true
set_interface_property clock_reset_reset EXPORT_OF ""
set_interface_property clock_reset_reset PORT_NAME_MAP ""
set_interface_property clock_reset_reset CMSIS_SVD_VARIABLES ""
set_interface_property clock_reset_reset SVD_ADDRESS_GROUP ""

add_interface_port clock_reset_reset reset reset Input 1


# 
# connection point clock_master
# 
add_interface clock_master clock end
set_interface_property clock_master clockRate 0
set_interface_property clock_master ENABLED true
set_interface_property clock_master EXPORT_OF ""
set_interface_property clock_master PORT_NAME_MAP ""
set_interface_property clock_master CMSIS_SVD_VARIABLES ""
set_interface_property clock_master SVD_ADDRESS_GROUP ""

add_interface_port clock_master master_clock clk Input 1


# 
# connection point clock_master_reset
# 
add_interface clock_master_reset reset end
set_interface_property clock_master_reset associatedClock clock_master
set_interface_property clock_master_reset synchronousEdges DEASSERT
set_interface_property clock_master_reset ENABLED true
set_interface_property clock_master_reset EXPORT_OF ""
set_interface_property clock_master_reset PORT_NAME_MAP ""
set_interface_property clock_master_reset CMSIS_SVD_VARIABLES ""
set_interface_property clock_master_reset SVD_ADDRESS_GROUP ""

add_interface_port clock_master_reset master_reset reset Input 1


# 
# connection point avalon_slave
# 
add_interface avalon_slave avalon end
set_interface_property avalon_slave addressAlignment NATIVE
set_interface_property avalon_slave addressUnits WORDS
set_interface_property avalon_slave associatedClock clock_reset
set_interface_property avalon_slave associatedReset clock_reset_reset
set_interface_property avalon_slave bitsPerSymbol 8
set_interface_property avalon_slave burstOnBurstBoundariesOnly false
set_interface_property avalon_slave burstcountUnits WORDS
set_interface_property avalon_slave explicitAddressSpan 0
set_interface_property avalon_slave holdTime 0
set_interface_property avalon_slave linewrapBursts false
set_interface_property avalon_slave maximumPendingReadTransactions 0
set_interface_property avalon_slave maximumPendingWriteTransactions 0
set_interface_property avalon_slave readLatency 1
set_interface_property avalon_slave readWaitStates 0
set_interface_property avalon_slave readWaitTime 0
set_interface_property avalon_slave setupTime 0
set_interface_property avalon_slave timingUnits Cycles
set_interface_property avalon_slave writeWaitTime 0
set_interface_property avalon_slave ENABLED true
set_interface_property avalon_slave EXPORT_OF ""
set_interface_property avalon_slave PORT_NAME_MAP ""
set_interface_property avalon_slave CMSIS_SVD_VARIABLES ""
set_interface_property avalon_slave SVD_ADDRESS_GROUP ""

add_interface_port avalon_slave slave_address address Input 5
add_interface_port avalon_slave slave_write write Input 1
add_interface_port avalon_slave slave_writedata writedata Input 32
add_interface_port avalon_slave slave_read read Input 1
add_interface_port avalon_slave slave_readdata readdata Output 32
set_interface_assignment avalon_slave embeddedsw.configuration.isFlash 0
set_interface_assignment avalon_slave embeddedsw.configuration.isMemoryDevice 0
set_interface_assignment avalon_slave embeddedsw.configuration.isNonVolatileStorage 0
set_interface_assignment avalon_slave embeddedsw.configuration.isPrintableDevice 0


# 
# connection point interrupt_sender
# 
add_interface interrupt_sender interrupt end
set_interface_property interrupt_sender associatedAddressablePoint avalon_slave
set_interface_property interrupt_sender associatedClock clock_reset
set_interface_property interrupt_sender associatedReset clock_reset_reset
set_interface_property interrupt_sender bridgedReceiverOffset ""
set_interface_property interrupt_sender bridgesToReceiver ""
set_interface_property interrupt_sender ENABLED true
set_interface_property interrupt_sender EXPORT_OF ""
set_interface_property interrupt_sender PORT_NAME_MAP ""
set_interface_property interrupt_sender CMSIS_SVD_VARIABLES ""
set_interface_property interrupt_sender SVD_ADDRESS_GROUP ""

add_interface_port interrupt_sender slave_irq irq Output 1

# -- Dynamic Ports (elaboration callback) --
set_module_property ELABORATION_CALLBACK vfr_elaboration_callback
proc vfr_elaboration_callback {} {
    # +-----------------------------------
    # | connection point avalon_streaming_source
    # | 
    set color_planes_in_parallel [get_parameter_value NUMBER_OF_CHANNELS_IN_PARALLEL]
    set bps [get_parameter_value BITS_PER_PIXEL_PER_COLOR_PLANE]
    set data_width [expr $bps * $color_planes_in_parallel]

    add_interface avalon_streaming_source avalon_streaming start
    set_interface_property avalon_streaming_source dataBitsPerSymbol $bps
    set_interface_property avalon_streaming_source symbolsPerBeat $color_planes_in_parallel
    set_interface_property avalon_streaming_source errorDescriptor ""
    set_interface_property avalon_streaming_source maxChannel 0
    set_interface_property avalon_streaming_source readyLatency 1

    add_interface_port avalon_streaming_source dout_data data Output $data_width
    add_interface_port avalon_streaming_source dout_valid valid Output 1
    add_interface_port avalon_streaming_source dout_ready ready Input 1
    add_interface_port avalon_streaming_source dout_startofpacket startofpacket Output 1
    add_interface_port avalon_streaming_source dout_endofpacket endofpacket Output 1    

    set_interface_property avalon_streaming_source ASSOCIATED_CLOCK clock_reset
    set_interface_property avalon_streaming_source ENABLED true 
    # | 
    # +-----------------------------------

    # +-----------------------------------
    # | connection point avalon_master
    # | 
    set mem_port_width [get_parameter_value MEM_PORT_WIDTH]
    add_interface avalon_master avalon start
    set_interface_property avalon_master burstOnBurstBoundariesOnly false
    set_interface_property avalon_master doStreamReads false
    set_interface_property avalon_master doStreamWrites false
    set_interface_property avalon_master linewrapBursts false

    set_interface_property avalon_master ASSOCIATED_CLOCK clock_master
    set_interface_property avalon_master ENABLED true

    set burst_target [get_parameter_value RMASTER_BURST_TARGET]
    add_interface_port avalon_master master_address address Output 32
    add_interface_port avalon_master master_burstcount burstcount Output [expr int(ceil((log($burst_target + 1))/(log(2))))]        
    add_interface_port avalon_master master_readdata readdata Input $mem_port_width
    add_interface_port avalon_master master_read read Output 1
    add_interface_port avalon_master master_readdatavalid readdatavalid Input 1
    add_interface_port avalon_master master_waitrequest waitrequest Input 1
    # | 
    # +-----------------------------------
}

どうやってこれを作った?

元の alt_vip_vfr_hw.tcl は、SOPC Builder の頃の tcl だったので、そのままでは Platform Designer では読み込めません。もちろん、tcl を一から解析して Platform Designer 用の記述にする事も可能です。しかし、それはちょっと骨が折れます。そこで、下記の手順で変換しました。

(1) Quartus II 13.1 を PC にインストールします。丁度この頃、 SOPC Builder から Qsys に切り替わる時期でしたので、SOPC Builder の tcl を Qsys でも読める機能がありました。

(2) Qsys の Component Editer でコアを開いて、閉じると、Qsys の tcl に変換してくれます。この時、気を付けないといけないのは、tcl の中に実行コード(上記のコードでは "# -- Dynamic Ports (elaboration callback) --" から下の部分)が含まれていると Component Editer で開けないので、tcl から実行コードを一旦削除した後、開く必要があります。

(3) 変換された tcl の実行コード部分を元に戻して、保存します。

これで、Platform Designer でも開ける IP コアが出来ました。ただ、全てこの方法で上手く行くかは分かりませんし、たとえ Platform Designer 上は上手く行っているように見えても、実装したコアが確実に動作するかも分かりませんので、自己責任でお願いします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerのコンテナを削除する方法

  • 環境
    • CentOS Linux release 7.6.1810 (Core)
    • Docker Version:18.09.6
コンテナを削除する
$ docker rm {コンテナID or コンテナ名}

削除する方法

# 停止しているコンテナを含めて全コンテナを表示する
$ docker ps -a
CONTAINER ID        IMAGE              COMMAND             CREATED             STATUS              PORTS                                              NAMES
dffe12345678        host_delete-target "/usr/sbin/init"    24 hours ago        Up 3 hours          0.0.0.0:18080->8080/tcp, 0.0.0.0:18082->8081/tcp   delete-target
93abcdefghij        host_hoge          "/usr/sbin/init"    4 months ago        Up 3 hours          0.0.0.0:8088->3389/tcp, 0.0.0.0:8089->8080/tcp     hoge

# 起動していたら停止する
$ docker-compose stop delete-target
Stopping delete-target ... done

# もう一回状態を見ておく
$ docker ps -a
CONTAINER ID        IMAGE              COMMAND             CREATED             STATUS                        PORTS                                             NAMES
dffe12345678        host_delete-target "/usr/sbin/init"    24 hours ago        Exited (137) 52 seconds ago                                                     delete-target
93abcdefghij        host_hoge          "/usr/sbin/init"    4 months ago        Up 3 hours                    0.0.0.0:8088->3389/tcp, 0.0.0.0:8089->8080/tcp    hoge

# 削除する
$ docker rm delete-target
delete-target

# 削除したコンテナがいなくなったことを確認する
$ docker ps -a
CONTAINER ID        IMAGE                               COMMAND             CREATED             STATUS              PORTS                         NAMES
93abcdefghij        host_hoge       "/usr/sbin/init"    4 months ago        Up 3 hours          0.0.0.0:8088->3389/tcp, 0.0.0.0:8089->8080/tcp    hoge

Stop the container before attempting removal or force remove

$ docker rm dffe12345678
Error response from daemon: You cannot remove a running container dffe... Stop the container before attempting removal or force remove
  • 原因 : コンテナを停止していないから
  • 対応 : コンテナを停止してから削除する

Can't find a suitable configuration file in this directory or any parent.

$ docker-compose stop delete-target
ERROR:
        Can't find a suitable configuration file in this directory or any
        parent. Are you in the right directory?

        Supported filenames: docker-compose.yml, docker-compose.yaml
  • 原因 : docker-compose.ymlのないディレクトリで操作するから
  • 対応 : 削除対象のdocker-compose.ymlのあるディレクトリで操作する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

phpとrsyncでNASのバックアップ

XubuntuとSambaで構築したNASにネットワーク共有用とバックアップ用それぞれ独立したHDDを載せた以下のような環境に対してrsyncでミラーリング及び世代管理バックアップを行う前提で記述したphpスクリプトです。
多少構成が異なっても応用はできるかと思います。

NAS用ドライブ
ルート直下に
/data/ … ネットワークドライブ用
というディレクトリを作成。
これをマウントポイント
/home/nas/
にマウントしてあり、
/home/nas/data/
をsambaで共有ディレクトリに設定することでNASのネットワークドライブとして使用。

バックアップ用ドライブ
ルート直下に
/data/ … ミラーリング用
/generation/ … 世代管理バックアップ用
というディレクトリを作成。
これをマウントポイント
/home/nas_backup/
にマウントすることで、
/home/nas_backup/data/
を/home/nas/data/のミラーリング先、
/home/nas_backup/generation/
を/home/nas_backup/data/の世代バックアップ先としています。

文字ではイメージが掴みにくいかもしれませんが、図にするとこんな感じになります。
blockimage.jpg

注意点としては、世代管理バックアップではハードリンクを活用するrsyncの--link-destオプションを使用しているので、対象ドライブはハードリンクを問題なく扱えるファイルシステムでないと世代管理バックアップのたびに毎回フルバックアップ相当のディスク消費と処理時間がかかると思われます。
私の場合はext4を使用しています。


スクリプト

mirroring.php
NAS共有ディレクトリをバックアップ元として、バックアップ先ドライブに対してrsyncの--deleteオプションを使用したミラーリングを行うスクリプトです。

mirroring.php
<?php
/**
 *  rsync ミラーリング
 */

// ミラーリング元ディレクトリ
define('SOURCE_DIR', '/home/nas/data/');

// ミラーリング先ディレクトリ
define('BACKUP_DIR', '/home/nas_backup/data/');

// その他のrsyncオプション 例: '--exclude=/temp/ --exclude=/*.bak';
define('OTHER_OPTIONS', '');

/**
 *
 */

set_time_limit(0);
date_default_timezone_set('Asia/Tokyo');

// 一時ファイル保存用ディレクトリ
define('TEMP_DIR', (file_exists('/dev/shm/') ? '/dev/shm/.' : '/var/tmp/.'). md5(__DIR__));
if(!file_exists(TEMP_DIR)) {
    mkdir(TEMP_DIR);
    chmod(TEMP_DIR, 0700);
}

$tempFile = TEMP_DIR. '/mirroring.tmp';
$temps = getTmpFile($tempFile);

// 各ディレクトリ名のデリミタ補正
$sourceDir = preg_replace('|/+$|', '/', SOURCE_DIR. '/');
$backupDir = preg_replace('|/+$|', '/', BACKUP_DIR. '/');

// バックアップ元・バックアップ先が無かったら終了
if(!file_exists($sourceDir) || !preg_match('/:/', $backupDir) && !file_exists($backupDir)) {
    print "The source '{$sourceDir}' or backup '{$backupDir}' destination directory does not exist.\n";
    exit;
}

// バックアップ元ディスク使用量をチェック、前回から変化が無ければ何もせず終了
// 但しリネームや小サイズの更新ではブロックサイズが変化しない場合もあるので
// 前回ミラーリングから1時間以上経過している場合はブロックサイズの変化に関わらずミラーリングを行う
exec("df {$sourceDir}", $ret);
$usedSize = (preg_split('/\s+/', $ret[1]))[2];
$prevUsedSize = isset($temps['prev_used_size']) ? (time() - filemtime($tempFile) < 3600 ? $temps['prev_used_size'] : 0) : 0;
if($usedSize == $prevUsedSize) exit;

// ロックファイル名
$lockFilename = TEMP_DIR. '/backup.lock';

// ロックファイルが存在していたら同名のプロセス実行中とみなし終了
if(file_exists($lockFilename)) {
    print "A process with the same name is running.\n";
    exit;
} else {
    // ロックファイル作成
    if(!@file_put_contents($lockFilename, 'Process is running.')) {
        print "Could not create `$lockFilename`.\nSet the permissions of the directory `". TEMP_DIR. "` to 0700.\n";
        exit;
    }
    chmod($lockFilename, 0600);
}

// tmpファイルに保存する情報更新
// ミラーリングの場合はバックアップ元の使用ブロック数
$temps['prev_used_size'] = $usedSize;
setTmpFile($tempFile, $temps);

$updateDirList = getUpdataDirList($sourceDir);
if(!$updateDirList) {
    $updateDirList[] = $sourceDir;
}

foreach($updateDirList as $dir) {
    $path = str_replace($sourceDir, '', $dir);
    // rsyncコマンド
    $command = implode(" ", [
            'rsync -avH',
            '--delete',
            OTHER_OPTIONS,
            '"'. preg_replace('/\/+$/', '/', ($sourceDir. $path. '/')). '"',
            '"'. preg_replace('/\/+$/', '/', ($backupDir. $path. '/')). '"',
        ]);
    print "$command\n";
    exec($command);
}

// ロックファイル削除
unlink($lockFilename);

exit;

/**
 *
 */

// tmpファイル取得
function getTmpFile($fn) {
    if(file_exists($fn)) {
        $tmp = file_get_contents($fn);
        return(json_decode($tmp, true));
    }
    return [];
}

// tmpファイル保存
function setTmpFile($fn, $temps) {
    if(getTmpFile($fn) != json_encode($temps)) {
        if(!@file_put_contents($fn, json_encode($temps))) {
            print "Could not create `$fn`.\nSet the permissions of the directory `". TEMP_DIR. "` to 0700.\n";
            exit;
        }
        chmod($fn, 0600);
    }
}

// 更新ディレクトリ取得
function getUpdataDirList($sourceDir) {
    $duFile = TEMP_DIR. '/prev_du.txt';
    $prevDirList = [];
    if(file_exists($duFile)) {
        $du = file_get_contents($duFile);
        $du = explode("\n", $du);
        foreach($du as $tmp) {
            if(!$tmp) continue;
            $l = explode("\t", $tmp);
            $prevDirList[$l[1]] = $l[0];
        }
    }

    exec("du {$sourceDir} > {$duFile}");
    chmod($duFile, 0600);
    $dirList = [];
    if(file_exists($duFile)) {
        $du = file_get_contents($duFile);
        $du = explode("\n", $du);
        foreach($du as $tmp) {
            if(!$tmp) continue;
            $l = explode("\t", $tmp);
            $dirList[$l[1]] = $l[0];
        }
    }
    unset($du);

    $tmpArr = [];
    foreach($dirList as $k => $v) {
        if(isset($prevDirList[$k]) && $prevDirList[$k] != $v) $tmpArr[$k] = $v;
    }

    $retArr = $tmpArr;
    foreach($tmpArr as $k => $v) {
        foreach($tmpArr as $k_ => $v_) {
            if($k == $k_) continue;
            if(isset($retArr[$k]) && strpos($k_, $k) === 0) unset($retArr[$k]);
        }
    }

    return array_keys($retArr);
}

バックアップ元ディスク容量が前回実行時から変化していなければrsyncは行わず終了するようにしてありますので頻繁に実行しても極端に負荷が高くなることは無いとは思いますが、その辺りは環境に合わせて加減してください。
容量チェックはdfコマンドを使用したものでファイル名の変更や小サイズの変更などブロックサイズの変化しない更新は察知できませんので、前回実行から1時間以上経過していたらバックアップ元ディスク容量が変化していなくてもrsyncを実行するようにしています。

主な設定項目

// ミラーリング元ディレクトリ
define(‘SOURCE_DIR’, ‘/home/nas/data/’);

ミラーリング元となるディレクトリを指定。

// ミラーリング先ディレクトリ
define(‘BACKUP_DIR’, ‘/home/nas_backup/data/’);

ミラーリング先となるディレクトリを指定。
こちらは先頭に「ユーザー名@ホスト名:」等を含めたリモートの指定も可能です。

define(‘BACKUP_DIR’, ‘username@hostname:/home/username/data/’);

リモートを指定した場合、cronでの自動実行時にはリモートへのログイン時にパスワード入力待ちが発生しないようパスワード無しでの公開鍵認証ログインができるよう適宜設定しておく必要があります。


generation.php
ミラーリングされたディレクトリを元に、世代管理用ディレクトリに対してrsyncの--link-destオプションを使用したバックアップを行うスクリプトです。
バックアップ用ドライブがNAS本体とは別のリモートにある場合はこのスクリプトもリモート側へ設置します。

generation.php
<?php
/**
 *  rsync 世代バックアップ
 */

// バックアップ元ディレクトリ
define('SOURCE_DIR', '/home/nas_backup/data/');

// バックアップ先ディレクトリ
define('BACKUP_DIR', '/home/nas_backup/generation/');

// その他のrsyncオプション 例: '--exclude=/temp/ --exclude=/*.bak';
define('OTHER_OPTIONS', '');

// バックアップ世代数
define('BACKUP_GENERATION', 200);

// 古いバックアップを削除するディスク容量閾値(%)
// 0の場合はディスク容量のチェックは行いません
define('THRESHOLD', 95);

/**
 *
 */

set_time_limit(0);
date_default_timezone_set('Asia/Tokyo');

// 一時ファイル保存用ディレクトリ
define('TEMP_DIR', (file_exists('/dev/shm/') ? '/dev/shm/.' : '/var/tmp/.'). md5(__DIR__));
if(!file_exists(TEMP_DIR)) {
    mkdir(TEMP_DIR);
    chmod(TEMP_DIR, 0700);
}

// 各ディレクトリ名のデリミタ補正
$sourceDir = preg_replace('|/+$|', '/', SOURCE_DIR. '/');
$backupDir = preg_replace('|/+$|', '/', BACKUP_DIR. '/');

// バックアップ元・バックアップ先が無かったら終了
if(!file_exists($sourceDir) || !file_exists($backupDir)) {
    print "The source '{$sourceDir}' or backup '{$backupDir}' destination directory does not exist.\n";
    exit;
}

$nowDate = date('Y-m-d_Hi');

// ロックファイル名
$lockFilename = TEMP_DIR. '/backup.lock';

// ロックファイルが存在していたら同名のプロセス実行中とみなし2分まで待機、その間に開放されなければ終了
$time = time();
while(file_exists($lockFilename)) {
    sleep(1);
    if($time + 120 < time()) {
        print "A process with the same name is running.\n";
        exit;
    }
}
// ロックファイル作成
if(!@file_put_contents($lockFilename, 'Process is running.')) {
    print "Could not create `$lockFilename`.\nSet the permissions of the directory `". TEMP_DIR. "` to 0700.\n";
    exit;
}
chmod($lockFilename, 0600);

// バックアップ済みディレクトリ名を取得
$backupList = getBackupList($backupDir);

// 古いバックアップを間引き
$processed = [];
foreach($backupList as $backupName) {
    if(!preg_match('/^(\d{4})-(\d\d)-(\d\d)_(\d\d)(\d\d)/', $backupName, $m) || isset($processed[$backupName])) continue;
    list($year, $month, $day, $hour, $minute) = array_slice($m, 1);
    $fDate = "$year-$month-$day $hour:$minute";

    // 1か月以上経過しているものはその月の最終のもの以外を削除
    if(time() >= strtotime("$fDate +1 month")) {
        $pickup = [];
        foreach($backupList as $tmp) {
            if(substr($tmp, 0, 7) == "{$year}-{$month}" && substr($tmp, 0, 10) <= "{$year}-{$month}-{$day}") $pickup[] = $tmp;
        }
        rsort($pickup);
        foreach(array_slice($pickup, 1) as $tmp) {
            deleteBackup($backupDir, $tmp, $processed);
        }
    }
    // 1日以上経過しているものはその日の最終のもの以外を削除
    elseif(time() >= strtotime("$fDate +1 day")) {
        $pickup = [];
        foreach($backupList as $tmp) {
            if(substr($tmp, 0, 10) == "{$year}-{$month}-{$day}" && $tmp <= $backupName) $pickup[] = $tmp;
        }
        rsort($pickup);
        foreach(array_slice($pickup, 1) as $tmp) {
            deleteBackup($backupDir, $tmp, $processed);
        }
    }
}
// バックアップ済みディレクトリ名を再取得
$backupList = getBackupList($backupDir);

// ディスク使用量が指定割合を下回るまで古いバックアップから削除
sort($backupList);
while(THRESHOLD && checkPercentage($backupDir) && count($backupList) > 1) {
    $command = "rm -rf {$backupDir}{$backupList[0]}";
    array_shift($backupList);
    print "$command\n";
    exec($command);
}

// 既存世代バックアップがある場合
if(count($backupList)) {
    rsort($backupList);
    // 保存世代数を超えるバックアップを古いものから削除
    if(count($backupList) >= BACKUP_GENERATION) {
        $delNames = array_slice($backupList, BACKUP_GENERATION -1);
        foreach($delNames as $del) {
            $command = "rm -rf {$backupDir}{$del}";
            print "$command\n";
            exec($command);
        }
    }
}

// 新規バックアップディレクトリ名
$backupName = "{$nowDate}/";

// rsyncコマンド
$command = implode(" ", [
        "rsync -avH",
        OTHER_OPTIONS,
        "--link-dest={$sourceDir}",
        $sourceDir,
        sprintf("%s%s", $backupDir, $backupName),
    ]);
print "$command\n";
exec($command);

// バックアップ済みディレクトリ名を再取得
$backupList = getBackupList($backupDir);
// 1世代前のバックアップとの差分でログのみ取得
if(count($backupList) > 1) {
    rsort($backupList);
    $command = "rsync -avHn --delete --exclude=/_rsync.log {$backupDir}{$backupList[0]}/ {$backupDir}{$backupList[1]}/ > {$backupDir}_rsync.log";
    exec($command);
    exec("mv {$backupDir}_rsync.log {$backupDir}{$backupList[0]}");
}

// ロックファイル削除
unlink($lockFilename);

exit;

/**
 *
 */

// 既存バックアップディレクトリ名取得
function getBackupList($backupDir) {
    $backupList = [];
    if($dir = opendir($backupDir)) {
        while($fn = readdir($dir)) {
            if(preg_match('/^\w{4}-\w{2}-\w{2}_\w{4,6}$/', $fn) && is_dir("{$backupDir}{$fn}")) {
                $backupList[] = $fn;
            }
        }
        closedir($dir);
    }
    return $backupList;
}

// バックアップ削除
function deleteBackup($backupDir, $str, &$processed) {
    if(isset($processed[$str])) return;
    if(file_exists("{$backupDir}{$str}")) {
        $command = "rm -rf {$backupDir}{$str}";
        print"$command\n";
        exec($command);
        $processed[$str] = 1;
    }
}

// ディスク使用量チェック
function checkPercentage($backupDir) {
    exec("df {$backupDir}", $ret);
    if(!isset($ret[1])) return false;
    if(preg_match('/(\d+)\%/', $ret[1], $ret)) {
        if($ret[1] >= THRESHOLD) return true;
    }
    return false;
}

実行日時を名前としたディレクトリを作成し、その中にその時点のバックアップを残していきます。
rsyncの--link-destオプションを使うことで新規追加や変化のあったファイルのみが実体として保存され、それ以外のファイルはハードリンクが追加されるだけですので、ディスク容量消費や処理時間は増分バックアップと同程度でありながら作成されるバックアップはそれぞれがフルバックアップ相当になるという特徴があります。
1日以上経過したバックアップはその日の最終版のみ残して削除、1か月以上経過したバックアップはその月の最終版を残して削除、THRESHOLDで指定したディスク使用量に達した場合は下回るまで古いバックアップから削除といった処理もこちらのスクリプトで行なっています。

ハードリンクを有効に活用するため--link-destには1世代前のバックアップを指定するのが一般的ですが、今回の場合$sourceDir自身が既にミラーリングされたバックアップの一部なのでこちらを--link-destに指定しています。
こうすることで、容量の節約と同時に処理速度の短縮も図れます。

主な設定項目

// バックアップ元ディレクトリ
define(‘SOURCE_DIR’, ‘/home/nas_backup/data/’);

mirroring.phpでミラーリング先となったディレクトリを指定します。

// バックアップ先ディレクトリ
define(‘BACKUP_DIR’, ‘/home/nas_backup/generation/’);

世代管理バックアップ保存先を指定します。
このディレクトリの下に
YYYY-MM-DD_HHMM
形式でディレクトリが作成され、その中に各世代のバックアップが保存されていきます。
rsyncの--link-destオプションを使用し変更のないファイルは実体ではなくハードリンクが作成されますので、必要以上にディスク容量を消費しません。

// バックアップ世代数
define(‘BACKUP_GENERATION’, 200);

保存したい世代数を指定します。
世代バックアップ数がこの値を超えたら古いバックアップから削除されますが、間引き処理やディスク容量による削除処理の兼ね合いで、ここで指定した数に達する前に削除が行なわれる場合もあります。

// 古いバックアップを削除するディスク容量閾値(%)
// 0の場合はディスク容量のチェックは行いません
define(‘THRESHOLD’, 95);

dfコマンドでバックアップ先のディスク使用量(%)をチェックし、この値に達していたら値を下回るまで古いバックアップから順に削除を行います。
0では削除処理を行わなくなりますが、バックアップ先の空き容量が足りなくてもrsyncの実行を抑制する等の処理は行いません。


crontab設定例

# rsync mirroring
* * * * * php /スクリプト設置パス/mirroring.php &> /dev/null
* * * * * sleep 30; php /スクリプト設置パス/mirroring.php &> /dev/null

# rsync generation backup
0 */6 * * * php /スクリプト設置パス/generation.php &> /dev/null

上記の例では前半ブロックで30秒ごとのミラーリングを、後半ブロックで6時間ごとに世代管理バックアップを行なっています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positionalとなった時の対応方法

  • 環境
    • CentOS Linux release 7.6.1810 (Core)
    • find (GNU findutils) 4.5.11

事象 : findに-maxdepthオプションをつけたらなんか注意された

$ find -type d -maxdepth 2
find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it).  Please specify options before other arguments.

.
./.settings
./src
./src/main
./src/test
./target
./target/classes
$

原因 : オプションの指定順序を間違えているから

注意文を訳してみた。やりたい気持ちの強い順にオプションを指定すればいいわけではない。

find:警告:オプションではない引数-typeの後に-maxdepthオプションを指定しましたが、オプションの位置が正しくありません(-maxdepthは、前に指定されたテストと後に指定されたテストに影響します。)。他の引数の前にオプションを指定してください。

使い方を見てみるとちゃんと「他の式の前に指定」って書いてある。

$ find --help
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
...省略...
# normal options (always true, (訳)他の式の前に指定):
normal options (always true, specified before other expressions):
      -depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf
      --version -xautofs -xdev -ignore_readdir_race -noignore_readdir_race

tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N
      -cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME
      -ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN -iregex PATTERN
      -links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE
      -nouser -nogroup -path PATTERN -perm [-/]MODE -regex PATTERN
      -readable -writable -executable
      -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N
...省略...

対応 : -typeの前に-maxdepthを指定する

注意されなくなった
$ find -maxdepth 2 -type d
.
./.settings
./src
./src/main
./src/test
./target
./target/classes
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む