Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

Spring Boot 2 + JQuery DataTablesで一覧画面を作成

f:id:fa11enprince:20200709020731j:plain
今更ながらjQuery系ですが、使ったことがなくてでも便利そうなので使ってみました。
皆さん大好きSpring Boot 2を使用しました。
また、Pagingが面倒なので皆さん大嫌いHibernateを利用しています。
結論としてはJQuery DataTablesは思ったより使いやすくて便利だ!ということです。
もしかして、サーバーから全件読まないとだめなやつ?と思いましたが、そんなことはなく、
serverSide: trueオプションをつけるとちゃんとサーバから10件取って、ページャー押したら10件取って、
が簡単に実現できます。

最終成果物

f:id:fa11enprince:20200709025621p:plain
画面は3画面作っていて、

  • 旧スタイルのサーバーサイドレンダリング(?)オンリーの画面
  • とりあえずのVueの画面
  • 今回本題のJQuery DataTablesを使用した画面

でできています。おまけ程度にログインもついています。

動作に必要なもの

Maria DB
bash (Git Bashとか)
Java 8
あとはそもそもGitにあがっているか、pom.xmlちゃんが引っ張ってきてくれます。

実行方法

EclipseでMaven installをして実行します。この場合Lombokが必要になります。
もしくは…

cd my-address-search
bash mvnw install
java -jar target/my-address-search-0.0.1-SNAPSHOT.jar

とかで実行してhttp://localhost:8080/でOKと思います。

編集、削除用のエリアは設けたものの見てお分かりの通り実装していないです。
github.com
ところどころ手を抜いているところはあるのであくまでサンプルとしてご容赦いただければ。
データはある程度多めのリアルのデータが良いということで、
郵便番号データを使用しています。
ただし、日本郵便で公開しているものは問題が多いCSVなので、
ここで公開させてくださっているありがたいデータを使っています。
zipcloud.ibsnet.co.jp

あと細かいところはGitHub上のREADME.mdを見ていただければと思います。

JQuery DataTableとSpring Bootの組み合わせの解説編

近日追記する予定です。わかる人はコードを見るとわかるかと…。

ハマった内容

応答が受け取れない

success: function(json) {
}

で受け取れない。
てか、なんとも言わず…ダメな感じになる。
こういう感じで何かサーバーのレスポンスをcallbackでごにょごにょしたいときは

dataSrc: function(json) {
}

というJQuery DataTableの専用のメソッドを使いましょう。
というか公式ドキュメント読まないとだめですね。
割と丁寧なドキュメントなので読みましょう。

Spring側でリクエストをマッピングできない

List<T>型を受け取れないのに、受け取れないということがありました。
具体的にはJavaScript側でソート内容を作ってサーバーに送り付けるのに、

var sortDatas = [];
for (var i = 0; i < data.order.length; i++) {
    var index = data.order[i].column;
    var direction = data.order[i].dir;
    var columnName = data.columns[index].data;
    var sd = {
        "direction": direction,
        "property": columnName,
    };
    sortDatas.push(sd);
}
...
orders: sortDatas, ...

のようなことをやって、

"orders": [{"direction": "asc", "property":"city"}, {"direction": "asc", "property":"district"}]

のようなソート順をサーバー側に渡したときに、JQuery DataTablesが
orders[0][property] = "city", orders[0][direction] = "asc"
としてしまいSpringのControllerの引数(リクエストパラメータ)処理側でどうにもならない問題です。
むりやりJacksonでCustom Json Desirializer的なものを書くのか??うーんと悩んでいましたが、
そもそもJQuery DataTablesが行っているSerializeを変えてやればいいというお話でした。
orders[0][property] = "city"orders[0].property = "city"に変えてやればSpring側で解釈できます。
そのために使っているのが、jquery.spring-friendly.jsです。

ここで気づいたのですが、そもそも便利なものがやはりあるのですね。 今回は自力で頑張っていますが、これを使えば一挙解決です。
github.com

Springでのエラーハンドリング

DataTables版では以前紹介した例外ハンドラ@RestControllerAdviceを使っています。
検索時の変な文字を突っ込んだ時にエラーを一応気持ち程度表示してます。
gup.monster

参考

DataTablesの使い方 - Qiita
Server-side processing

Spring Bootでマルチデータソースのやり方

f:id:fa11enprince:20200613105140j:plain 以前このブログで紹介したMaven + Eclipseでマルチモジュールプロジェクトを作成するのなかでサンプルコードで示したものの特にマルチデータソースのやり方についての解説です。
gup.monster
この記事に書いてある通り、PostgreSQLとMongoDBを組み合わせる場合を例として書いてあります。

完成版のソースコードはこちらです。
github.com

ミドルウェア バージョン
Spring Boot 2
Java 1.8
Apache Maven 3

細かいバージョンはGitHubを参照してください。

Spring-Data-JPAとSpring-Data-MongoDBを利用した場合のやり方を解説します。

構成の概要

プロジェクト/モジュール/パッケージは次のようになっています。
2モジュールありmulti-module-batchはサンプルを動かす利用側コード
multi-module-commonはデータアクセス系を提供する共通モジュールの位置づけです。
f:id:fa11enprince:20200613104405p:plain

設定ファイル

PostgreSQLとMongoDBを利用する場合を考えてみます。
まずは設定ファイルの構成を考えます。
application.yml

spring:
  datasource:
    postgres:
      url: jdbc:postgresql://localhost:5433/postgres
      username: postgres
      password: postgres
    mongo:
      host: localhost
      port: 27018
      database: mongo
  profiles:
    include: common

重要なところのみ抜粋です。
このように利用する側の設定で、ユーザ名、パスワード、データベースを指定できれば設定ファイルとしては十分かと思います。
また、このプロジェクトではマルチモジュールを採用していてデータベースアクセス部分はcommonのプロジェクトが別にいます。
例えばコネクションプール系の設定はだいたい一緒でいいだろうというのがあると思いますので、
commonの設定に切り出したいとします。
それがinclude: commonの部分です。この場合Springがapplication-common.ymlという設定ファイルを追加で読み込みます。

共通モジュール側のプロジェクトのapplication-common.yaml

packages:
  common:
    component: com.example.multiModule
    postgres:
      entity: com.example.multiModule.common.spring.postgres.entities
      repository: com.example.multiModule.common.spring.postgres.repositories
    mongo:
      entity: com.example.multiModule.common.spring.mongo.entities
      repository: com.example.multiModule.common.spring.mongo.repositories

spring:
  datasource:
    postgres:
      driver-class-name: org.postgresql.Driver
    hikari:
      minimum-idle: 2 # Default: Same as maximum-pool-size
      maximum-pool-size: 4 # Default: 10
      idle-timeout: 60000 # Default: 60seconds
      connection-timeout: 30000 # Default: 30000
      leak-detection-threshold: 5000 #5sec Default: 0 -> disable
      max-lifetime: 600000 # 10min, Default: 1800000 (30 minutes)

使用するドライバとコネクションプールの設定です。
Mongoは今回特にこれに相当する設定をしないので、省略しています。
packagesの設定は@EnableJpaRepositories, @EnableMongoRepositoriesで利用します。

マルチデータソースの場合、Configを個別に用意してあげる必要があります。

マルチデータソースの場合、Configを個別に用意してあげる必要があります。
こちらのプロジェクトではデータアクセスにかかわる部分、RepositoryとEntittyも実装します。
また、Serviceも今回こちらに実装します。
基本的に定型の設定をコードベースで書くことになります。ある意味覚えゲーです。

PostgreSQL設定

ポイントとなるのはPostgresConfig.javaMongoConfig.javaです。

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    basePackages = {"${packages.common.postgres.repository}"},
    entityManagerFactoryRef = "postgresEntityManagerFactory",
    transactionManagerRef = "postgresTransactionManager"
)
@EntityScan(basePackages = { "${packages.common.postgres.entity}" })
public class PostgresConfig {

    @Autowired
    PackageConfig packageConfig;

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.postgres")
    public DataSourceProperties postgresDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("spring.jpa.postgres")
    public JpaProperties postgresJpaProperties() {
        return new JpaProperties();
    }

    @Bean(name = "postgresDataSource")
    @ConfigurationProperties("spring.datasource.hikari")
    public HikariDataSource dataSource(DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    }

    @Bean(name = "postgresEntityManagerFactory")
    @Primary
    public LocalContainerEntityManagerFactoryBean postgresEntityManagerFactory(
            final EntityManagerFactoryBuilder builder,
            @Qualifier("postgresDataSource") final DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages(packageConfig.getCommon().getPostgres().getEntity())
                .persistenceUnit("postgres")
                .properties(postgresJpaProperties().getProperties())
                .build();
    }

    @Bean(name = "postgresTransactionManager")
    @Primary
    public PlatformTransactionManager postgresTransactionManager(
            @Qualifier("postgresEntityManagerFactory") final EntityManagerFactory entityManagerFactory) {
        final JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }
}

カスタムで設定を書くので@EnableTransactionManagement, @EnableJpaRepositoriesの指定は必須となります。
後者の@EnableJpaRepositoryですが@Repositoryをついたクラスを検索してBeanとして登録するためのものです。
また、マルチモジュールにしている関係でEntityの場所がどこ?となってしまうので@EntityScanを指定してやる必要があります。

各メソッドの説明

設定値を読む用のメソッドもあったりして厄介ですが、このクラスのメソッドで絶対に書かなければならないのが、3つあります。

    @Bean(name = "postgresDataSource")
    @ConfigurationProperties("spring.datasource.hikari")
    public HikariDataSource dataSource(DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    }

これが1つ目です。HikariCPを使うようにしています。
さらにDataSourceProperties経由でjdbcドライバ等の設定を読むようにしています。
名前が被るのでBean名をアノテーションで変更してあげます。ここではpostgresDataSourceとしています。
細かい内容はこの辺りの内容が参考になると思います。
https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-data-access

2つ目が

    @Bean(name = "postgresEntityManagerFactory")
    @Primary
    public LocalContainerEntityManagerFactoryBean postgresEntityManagerFactory(
            final EntityManagerFactoryBuilder builder,
            @Qualifier("postgresDataSource") final DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages(packageConfig.getCommon().getPostgres().getEntity())
                .persistenceUnit("postgres")
                .properties(postgresJpaProperties().getProperties())
                .build();
    }

です。なんとも長ったらしいメソッドですが、
LocalContainerEntityManagerFactoryBeanを返すメソッドを作ってやらなければなりません。
エンティティ登録管理のファクトリを教えてくれってことですね。Springムズカシイ。
補足ですがアノテーションの@QualifierはどのDataSourceよってSpringがわかんないので、
さっき定義したpostgresDataSouceっすよってことで教えてあげます。
しばらく触ってないと忘れがちですが@Beanによってクラスを返すメソッドを定義してSpring Beanにすると @Autowiredで注入できるのですよね。
何を言っているのかわからねー、という人はここがわかりやすいかなと思います。
dev.classmethod.jp
紛らわしいのが単にgetter/setterの塊のJava Beans。これとは違う用語なので混同しないでくださいね。

3つ目、

    @Bean(name = "postgresTransactionManager")
    @Primary
    public PlatformTransactionManager postgresTransactionManager(
            @Qualifier("postgresEntityManagerFactory") final EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

これも先ほど同様にな感じで先ほど定義したBeanを注入して設定する、な感じです。

MongoDBの設定

Spring-Data-MongoDBを利用する前提です。
こちらはずいぶんシンプルです。設定の読み込みをのぞけば2メソッド書けば終わりです。
また、@EnableMongoRepositories@EntityScanを書く必要があります。後者はマルチモジュールにしているためですね。

@Configuration
@EnableMongoRepositories(basePackages = { "${packages.common.mongo.repository}" })
@EntityScan(basePackages = { "${packages.common.mongo.entity}" })
public class MongoConfig {
    
    @Autowired
    MongoMappingContext mongoMappingContext;
    
    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.mongo")
    public MongoProperties mongoProperties() {
        return new MongoProperties();
    }

    @Bean
    @Primary
    public MongoClient mongo() {
        return new MongoClient(mongoProperties().getHost(), mongoProperties().getPort());
    }

    @Bean
    @Primary
    public MongoTemplate mongoTemplate() throws Exception {
        MongoDbFactory factory = new SimpleMongoDbFactory(mongo(), mongoProperties().getDatabase());
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
        MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));  // remove _class
        
        return new MongoTemplate(factory, converter);
    }
}

各メソッドの説明

    @Bean
    @Primary
    public MongoClient mongo() {
        return new MongoClient(mongoProperties().getHost(), mongoProperties().getPort());
    }

解説不要そうなこちらと

    @Bean
    @Primary
    public MongoTemplate mongoTemplate() throws Exception {
        MongoDbFactory factory = new SimpleMongoDbFactory(mongo(), mongoProperties().getDatabase());
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
        MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));  // remove _class
        
        return new MongoTemplate(factory, converter);
    }

こちらが必要です。実はこちらについては

public MongoTemplate mongoTemplate() throws Exception {
    return new MongoTemplate(
              new SimpleMongoDbFactory(new MongoClient(mongo.getHost(), mongo.getPort()), mongo.getDatabase()));
}

と書くだけでよいのですが、デフォルトのまま使うとすべてのコレクションのドキュメントに_classと勝手にフィールドがつくのでそれが嫌だったので消す設定を追加しています。
以上で終わりです。

どう使えばいいのか

それで、このように定義した場合後はどうすればいいかというとEntityとRepositoryの置き場さえ守れば、
通常通りEntityとRepositoryを書けます。
PostgreSQLの場合、@EnableJpaRepositoriesと設定ファイルで、
Entity: com.example.multiModule.common.spring.postgres.entities
Repository: com.example.multiModule.common.spring.postgres.repositories
とパッケージを指定してあげてます。
Mongoの場合もほぼ同様で、
Entity: com.example.multiModule.common.spring.mongo.entities
Repository: com.example.multiModule.common.spring.mongo.repositories
つまり、PostgreSQLはpostgesパッケージ配下、MongoDBはmongoパッケージ配下に書けばよいことになります。

詳細はGitHubのリンクを参照してください。

備考

multi-module-batchにある利用する側のモジュールのコードです。

@SpringBootApplication
@ComponentScan(basePackages = { "${packages.common.component}", "${app.packages}" })
public class SampleDbAccessApp implements ApplicationRunner {
    @Autowired
    PosgresSampleService postgresSampleService;
    @Autowired
    MongoSampleService mongoSampleService;
    
    public static void main(String[] args) {
        SpringApplication.run(SampleDbAccessApp.class, args);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        PostgresSample postgre = new PostgresSample();
        postgre.setName("John");
        postgresSampleService.save(postgre);
        List<PostgresSample> findResult1 = postgresSampleService.findAll();
        findResult1.forEach(System.out::println);
        
        MongoSample mongo = new MongoSample();
        mongo.setName("Kate");
        mongoSampleService.save(mongo);
        List<MongoSample> findResult2 = mongoSampleService.findAll();
        findResult2.forEach(System.out::println);
    }
}

1点言うことがあるとすれば、マルチモジュールプロジェクトで、コンポーネントのScanする場所が変わっています。
この場合、multi-module-commonプロジェクト配下なので、@ComponentScanで指定してあげる必要があります。 変数を使っていますが、これはAppConfig.javaにより定義して設定値から読み取っています。

使う側から見ると何の変哲もない感じで自然に扱えます。

参考

Spring bootでマルチデータソース対応の実装方法(MybatisとSpring Data JPA ) - Qiita
5.1. データベースアクセス(共通編) — TERASOLUNA Server Framework for Java (5.x) Development Guideline 5.0.1.RELEASE documentation
Multiple MongoDB connectors with Spring Boot

ColorfulBoxでWordPressを運営する

f:id:fa11enprince:20200605032929j:plain
全くこことは別のジャンルのブログを、レンタルサーバーでWordPressを動かすときの備忘録です。
なんでColorfulBoxを選んだかというと安くて速いからです。

1サーバーで独自ドメインで複数WordPressで運営することを見越した設定にします。
どうせ大したアクセスが来ないので、費用を安く抑えようという魂胆です。
複数のドメインを取って1サーバーで運営するときの手順です。
サイトを増やしたいときにサーバーを増やさずにドメインだけ増やしたいっていうニーズの場合の対応策です。
1サーバー1ドメインの時とほぼ変わりません。
最初のサーバー購入のところでちょっと手順が変わるくらいでしょうか。
この方法でやるとpublic_html配下にちゃんとドメインごとにディレクトリが切られます。
もちろんデータベースも自動的に分けて作ってくれます。賢い。
スクリーンショットはありませんが、レンタルサーバーを触ったことがない人でもなんとなくわかると思います。
ただ、ある程度Webの知識はないとどこかで意味わからん状態になるかもしれません。
その場合、ほかに丁寧に解説しているサイトが数多くあると思うので、そちらを参照していただいて、
こちらは、1サーバー複数ドメインを実現する方法に集中して書きます。

ColorfulBoxでサーバー購入

詳しいことは公式で。とにかく安くて速くておすすめです。
LiteSpeedというWebサーバーを使ってるのも特徴的です。
www.colorfulbox.jp 880円のサーバーがコスパ良しという感じでしょうか。
最安値の480円でもそこそこ使えるとは思います。
でもブログを快適に運営したいなら880円のが無難でしょうね。

ドメイン取得

先にColorfulBoxから(実際にはGMO経由)、ドメインを取得する。
値段がお名前.comと初期費用が誤差程度に微妙に違ったかと思います。
ColorfulBox使うなら一元管理ができるので、こちらで買ったほうが良いかと思います。

サーバー購入

1サーバー複数WordPressを見越しているのでとりあえずは無料サブドメインで作成する。
そのため購入の段階ではWordPress快速セットアップは利用しない。
これをしてしまうとpublic_html配下をそのまま使ってしまう?(試してないので詳細不明)。
ドメインを取ったことがない人にとっては罠になりがちなのが、初期費用と維持費用(更新料)に相関がないことです
騙されないようにするには、初期費用と更新料の表を自分で作成して更新料順でソートして比較してみることをお勧めします。
一般的には.com, .net, 最近出てきた(人気がなさそうな)新gTLDが安いです。

DNS設定

ドメイン > DNSの管理 > 編集でDNSマネージャーへ移動 保留中なら待ちます。 ドメインを取得した直後や、ネームサーバーを変更した直後は保留中で、最大で24時間程度待ちます。

DNSのレコードセットを変更

https://help.colorfulbox.jp/manual/domain-dns-control/
上記URLで自サーバー名を調べ、そのレコードセットを選ぶ、「既存の設定を削除する」をチェックし、実行します。
設定の反映処理が実行されるまでに最大で5分程度かかります。
そうするとAレコード、MXレコード、NSレコード、TXTレコードが自動で設定されアクセスできるようになります。 また、保留中になるのでしばらく待ちます。

アドオンドメイン追加

https://help.colorfulbox.jp/manual/original-domain-conf/
cPanelからアドオンドメインを追加
自分で購入したドメインを新しいドメイン名 に入力します。
(サブドメインは自動入力で、サブディレクトリも切られます)
「ドメインの追加」を押下します。

さらにしばらく待てばAutoSSLが反映され、httpsでアクセスできるようになります。 ドメイン認証型のSSLとのこと。
https://help.colorfulbox.jp/manual/free-ssl-trouble/
この設定をするまでSSL設定が失敗しているはずなのでAutoSSLを実行します

httpからhttpsへのリダイレクト

Colorfulboxの場合、さらにhttpからhttpsへのリダイレクトの設定が必要になります。
httpでアクセスしてくる人がたまにいるかもしれないのでhttpsに切り替えます。
https://help.colorfulbox.jp/faq/url-redirect/
単にリダイレクトでhttps://[ドメイン]/とすればOKです。

WordPressインストール

購入済みサーバーからcPanelにログインします。
Web ApplicationsセクションからWordPressを選択し、「このアプリケーションをインストール」をクリックし、
自分のドメインをHTTPSで設定、このときnaked domainでやっちゃいます(CDNは使わないしデメリットないはず)。

自動アップデートの設定はお好みですが、こまめに自分でメンテすることを考えて、 次のような感じにします。WPは壊れやすいので。

自動アップデート  
 任意の新しいバージョンへのバックアップや更新を作成します。  
WordPressプラグインの自動更新  
 自動的WordPressプラグインを更新しないでください。  
WordPressテーマ自動更新  
 自動的WordPressテーマを更新しないでください。  
Automatic Update Backup  
 Create a backup and automatically restore the backup if the update fails.  
を選びます。  
Two-Factor Authentication  
 Do not enable two-factor authentication.  
ログイン試行回数を制限する?  
 はい、制限が強化されたセキュリティのためのログイン試行に失敗しました。 (推奨)  
マルチサイトを有効にしますか?  
 いいえ、有効にしないでください。マルチサイトは、ワードプレスの中に、後で有効にすることができます。 (推奨)  
高度な設定管理
 自動的に私のための高度な設定を管理します。

紛らわしいですが、マルチサイトと複数ドメインは別の話で、同じユーザでログインして一括で管理できる仕組みですが、
正直一人だとこの機能微妙な気がします。
あれ?よくわかんなくなってきた。これサイトドメインと同じことをいっているのか?
これ、基本OFFっていいはずです。
たいして重要ではないので気が向いたときに調べよう。
DBの保存先は少なくともバラバラになります。

WordPressの設定

あとは煮るなり焼くなり
最低限やることを列挙します。

一般的な設定

・ユーザ
  言語 日本語
  ニックネームとブログ上の表示名を変更
  プロフィール写真をGravatarで登録したほうが良い(推奨)

・タイムゾーン
設定 > 一般 > タイムゾーン
  東京
  日付フォーマット Y-m-d
  時刻フォーマット H:i
  週の始まり 日曜日
・パーマリンク設定
設定 > パーマリンク設定
  好みだが数字ベースに

プラグイン

あとはJetPackいれとく

Akismet Anti-Spam (アンチスパム)
Hello Dolly

はそっこーで削除します。

サイトネットワークは必要性を感じてないので設定していません。
https://ja.wordpress.org/support/article/network-admin-sites-screen/

グローバルナビ

外観 > メニューで グローバルナビを選びます。 プライバシーポリシーを追加します。 メニューの位置は空で良いです。この場合、ヘッダー下のグローバルメニューに追加されます。

テーマの設定

https://wp-cocoon.com/
お好みですが、Cocoonを選びました。

番外編

よっぽどのことがない限り必要ないですが…一応記載しておきます。

SSHアクセスを設定する

1か所注意するところがあるとすれば、SSHの公開鍵をauthorizeにすること https://help.colorfulbox.jp/manual/ssh-use/

キャッシュのクリア

cPanelの詳細欄のLiteSpeed Web Cache Managerから消せる
テーマ変えたときとか、WordPressのバージョン変えたときに使うかもしれない。

レンタルサーバー便利ですね。VPSはいろいろいじくらせてくれるけどダルい。WAFついてこないしね。
AWSは個人で使うには堅牢な感じだし、オーバースペックだし、従量課金なのがね。
IAMとかVPCとかの管理も個人でやるにはだるいし。EBS高いしかといってS3もだるいし。
ALB/ELB/RDSなんて個人じゃまず使わないだろうし。
仕事でWebサーバーを立てる場合はAWS一択にほぼなるんですけどね。

GPU付きマシンでUbuntu 18.04.4 LTS Desktop amd64をLive DVDを動かしてデータ消去

f:id:fa11enprince:20200531020724j:plain
例によって備忘録です。これから試すところも書いてあります(特にデータ消去)。
データ消去は結構課題ですね。
Windowsなら結構いいソフトがあるとは思うのですが、
ddコマンドで乱数を書いてデータ消去というのをどんなOSのものであってもやりたいことがあります。
そんなときに使えそうな、DBANは古くからありますが、
そもそもLegacyモードでしか起動しないのと、SSDを認識してくれません。困った。
とはいえ大半のBIOSにデータ消去機能が入っていたリハするのですが…たまにないやつがいる。
さてどうしようとなるわけで、そうだ、Ubuntuをインストールして、shredコマンドで消そうと思いっ立ったのです。 しかしそもそもUbuntuを入れようとするとハマりポイントがいっぱい。

前提条件

この前提条件が違うとうまくいかない可能性があります。特にBIOSとハードウェアが絡んでくるかもしれません。
Ubuntu 18.04.4 LTS Desktop amd64

ソフト バージョン 備考
OS Windows 10 DVD作成+編集用
GPU NVIDIA Geforce RTX 2070 Super
チップセット Z390M-S01

ファイラーを開いてOther Locationsというところを押すとWindowsで使っていたディスクが見えると思います。

ISOをダウンロードします

http://releases.ubuntu.com/18.04.4/
ここからデスクトップ版をダウンロードします

Rufasを使ってUSBに書き込みます

このときDVDでもいいのですが、ハマり回避のためにUSBのほうが良いかと思われます。
というのもGPU付きマシンだとドライバが入ってないという罠があるので、そのまま突き進むとプチ砂嵐になるので、
Windows上からgrubのテキストファイルを書き換える必要が出てきます。

書き込むときも罠があります。 基本Secure BootがONでCSMもON、UEFIモードでやりたいので、このようにします。
何のことかピンとこない場合は、とりあえず普通にWindows 10を使っている場合、こうなってるはずです。

GPT UEFI(CSM無効)の組み合わせでUSBを作成

GPT UEFI(CSM)無効の組み合わせでUSBを作成します。あとは設定をいじらなくてOKです。
こうするとBIOSの設定がCSM: Enable, Boot: UEFI Only, Secure Boot: Enable1 の状態でインストールできる(Secure Boot Disableにしたほうが良いという説もある)。 あえてレガシーでやりたい場合は
MBR BIOSまたはUEFIで書き込んで、
BIOSの設定がCSM: Disable, Boot: Legacy First, Secure Boot: Disableとかでインストールできるはず…だが、検証した時は時間がなくてよくわからず。
まぁ、このニーズはあまりないんでないかな。というかMSIの場合、Windowsを消さないとどうもLegacyに変えられないっぽい。

USBの内容を書換え

2か所書き換えます。実は前者は不要だと思われます。
マウントされているUSBドライブをのぞくと普通にファイルが見えるので次のファイルを開きます。
先頭の行数と-+はないですが、diffっぽい形式で書いてます。
要はquiet splashnomodesetに書き換えます。
isolinux/txt.cfg

 5 - append  file=/cdrom/preseed/ubuntu.seed boot=casper initrd=/casper/initrd quiet splash ---
 5 + append  file=/cdrom/preseed/ubuntu.seed boot=casper initrd=/casper/initrd nomodeset ---

 9 - append  file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity initrd=/casper/initrd quiet splash ---
 9 + append  file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity initrd=/casper/initrd nomodeset ---

13 - append  boot=casper integrity-check initrd=/casper/initrd quiet splash
13 + append  boot=casper integrity-check initrd=/casper/initrd nomodeset ---

こちらも同じ要領で書き換えます
boot/grub/grub.txt

16 -    linux    /casper/vmlinuz  file=/cdrom/preseed/ubuntu.seed boot=casper quiet splash ---
16 +    linux    /casper/vmlinuz  file=/cdrom/preseed/ubuntu.seed boot=casper nomodeset ---

21 -    linux   /casper/vmlinuz  file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity quiet splash---
21 +    linux   /casper/vmlinuz  file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity nomodeset ---

26 -    linux   /casper/vmlinuz  file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity quiet splash oem-config/enable=true ---
26 +    linux   /casper/vmlinuz  file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity quiet splash oem-config/enable=true ---

なおこれらをやらなくても、起動時に下記をやるとOK
タイミングが約3秒と厳しく下手するとやり直しになる方法
nVidiaのGPU搭載PCにUbuntuを入れようとしてハマった - Qiita
起動時に黒画面で即eを押した後 quiet splashをnomodesetに書き換えてF10をおせばできる

quiet splashってなに?ってのはこちら
boot - What do the nomodeset, quiet and splash kernel parameters mean? - Ask Ubuntu

Windowsをリカバリーモードで再起動してUSBから起動

詳細は割愛しますが、USBから起動してもいいし、いったんBIOSのデバイスのBoot順を変更してやってもいいかもしれません。
ただ、再起動のタイミングによってなのか、USBを選べない時がありますので、
BIOSのデバイスのBoot順をUSBを最初に持ってきましょう。

Try Ubuntu without installingを選ぶ

これを選ぶと難なくUbuntuの画面が表示されると思います。
これでダメな場合、何らかの対処が必要です。

データ消去を試みる

Ubuntuのファイラーを開いてOther Locationsを選択するとWindowsで使っていたドライブが/dev/nvme0n1p3とか/dev/sda2とかで見れると思います。
もしくはsudo fdisk -lで見れるかと思います。
あとはTerminalから

$ shred -v -n 3 -z /dev/nvme0n1p3

とやればデータを消せると思いますが、ここはまだ実施してません。

Ubuntuのインストール毎回ハマってる気がする…。

Linux Mintを使ってみた

試しに昔使ったことのあるLinux Mintはどうだろうということで、何も考えずに下記からISOをダウンロードしてインストールする。
Ubuntu 16.04ベースのLinux Mint 18.1 Sarahを使用
linuxmint-jp.net
ISOをダウンロードしたらWindowsの標準機能で右クリックして、「ディスクイメージの書込み」を選ぶ。 DVD-Rに書き込んだ。 そして試しにUEFIモードでセキュアブートのままDVDから起動すると…
何事もなくライブDVDが立ち上がった。
これでいいんじゃないかと思った…。
ちなみに途中で2回ほどCUIでログインプロンプトが表示されますが、無視してたら勝手に処理が進っぽいです。
なんか入れないとだめかなと思って1回だけlogin: rootって打ち込んでしまいましたが。
ちなみにnouveauとか途中ででてくるのでGPUに対して何かしようってのはあるんだとおもいます。
f:id:fa11enprince:20200531042921p:plain
こんな感じでWindowsに寄せてます。


  1. これはMSIのBIOSの表記ではなくよくあるBIOSの表記です。