手元のノートPCに、遠くにある Linux-Kusanagi サーバーと同じ環境を構築し、Mediawiki をインストールし、Wikipedia 日本語版のクローンをつくってみた。
頻繁に途切れるネット接続に惱まされることなく、ローカルPCで開発できるようにする。
結構はまったのでまた嵌らないように、再現できるように手順を記録しておく。
最初のPC環境: NEC ノートPC LAVIE Direct HZ (PC-GN276W1AA)
Windows 10 Home
CPU Core™ i7-7500U
SSD 500GB
メモリ 8GB
KUSANAGI for Vagrant のインストール
1.KUSANAGI for Vagrant をインストールする。
2. KUSANAGIの初期設定
ここではまる。最初の
# yum --enablerepo=remi,remi-php56 update -y
で、エラーが大量に出て進まない。
これは
yum clean all
で解決。
Nginx, php7 を選択。
3. KUSANAGIのプロビジョニング
個別のドメインがヱブでアクセスできるようにする。WordPress もインストールできる。
今回はダウンロードしてきたMediaWikiをインストールするので、空の LAMP 環境を設定するだけ。
# kusanagi provision –lamp mywiki
4. MediaWiki のインストール
# cd /home/kusanagi/mywiki/DocumentRoot/ wget https://releases.wikimedia.org/mediawiki/1.31/mediawiki-1.31.0.tar.gz tar xvzf mediawiki-*.tar.gz cd mediawiki* mv * ../
これで、設定したドメイン名が mywiki.npn だとすると、
でアクセスできるようになる。
Mediawiki の設定+インストール画面が現れるので、最後まで進む。
警告: Unicode 正規化の処理に intl PECL 拡張機能を利用できないため、処理が遅いピュア PHP の実装を代わりに使用しています。
Mediawiki のインストール画面の最初の方で、「警告: Unicode 正規化の処理に intl PECL 拡張機能を利用できないため、処理が遅いピュア PHP の実装を代わりに使用しています。」
という警告が出る。
そのまま無視して次に進むこともできるが、この警告をなくすためには intl PECL 拡張機能 をインストールしてみる。
PHP intl が有効になっているかどうかを確認する。
# php -i | grep intl intl intl.default_locale => no value => no value intl.error_level => 0 => 0 intl.use_exceptions => 0 => 0
このように表示されなくて、何も表示されなければ、intl は有効になっていないということ。
yum install icu libicu-devel
# php -v PHP 7.2.8 (cli) (built: Jul 31 2018 12:48:51) ( NTS ) //現在のPHP7のバージョンに最適な intl 検索 # yum list | grep intl php72-php-intl.x86_64 7.2.8-1.el7.remi @remi intltool.noarch 0.50.2-7.el7 base mintlocale.noarch 1.4.4-1.el7 epel mintlocale-set-default-locale.noarch 1.4.4-1.el7 epel perl-libintl.x86_64 1.20-12.el7 base php-aura-intl.noarch 3.0.0-1.el7.remi remi php-intl.x86_64 5.4.45-14.el7.remi remi php-symfony-intl.noarch 2.8.42-1.el7.remi remi php-symfony3-intl.noarch 3.4.12-1.el7.remi remi php-symfony4-intl.noarch 4.0.11-1.el7.remi remi php54-php-intl.x86_64 5.4.45-14.el7.remi remi php55-php-intl.x86_64 5.5.38-8.el7.remi remi php56-php-intl.x86_64 5.6.37-1.el7.remi remi php56u-intl.x86_64 5.6.36-1.ius.centos7 ius php70-php-intl.x86_64 7.0.31-1.el7.remi remi php70u-intl.x86_64 7.0.30-1.ius.centos7 ius php71-php-intl.x86_64 7.1.20-1.el7.remi remi php71u-intl.x86_64 7.1.19-1.ius.centos7 ius php72-php-intl.x86_64 7.2.7-2.-1.el7.remi remi php72u-intl.x86_64 7.2.7-2.ius.centos7 ius php73-php-intl.x86_64 7.3.0~alpha4-1.el7.remi remi //インストール yum install php72-php-intl.x86_64 # php -i | grep intl # updatedb locate intl.so /opt/remi/php72/root/usr/lib64/php/modules/intl.so
/opt/remi/php72/root/usr/lib64/php/modules/
の中に .so ファイルがいくつも生成されているから、現在の extension_dir を確認して、その下に全部移動する。
# php -i |grep extension_dir extension_dir => /usr/local/php7/lib/php/extensions/no-debug-non-zts-20170718 => /usr/local/php7/lib/php/extensions/no-debug-non-zts-20170718 # mv /opt/remi/php72/root/usr/lib64/php/modules/* /usr/local/php7/lib/php/extensions/no-debug-non-zts-20170718/ # nano /etc/php7.d/php.ini extension=intl.so //この行を追加
これで再起動すれば intl が有効化されているだろう。
ビジュアルエディタをメディアヰキ に追加
5.Visualeditor をMediaWiki に追加するために Parsoid をインストールする。
cd /opt yum install git npm git clone --recursive https://gerrit.wikimedia.org/r/p/mediawiki/services/parsoid/deploy git clone https://gerrit.wikimedia.org/r/p/mediawiki/services/parsoid cd parsoid npm install cp config.example.yaml config.yaml nano config.yaml
この赤部分だけ自分のドメイン名に変えればよい。他の部分は
mwApis: - # This is the only required parameter, # the URL of you MediaWiki API endpoint. uri: 'http://mywiki.npn/api.php' domain: 'mywiki.npn' # optional
ここで注意すべきは、日本語ドメインの場合は、Punycode ではなくて、日本語そのままを記入しないと正常に動作しなかった。ポート8000が使用されなかった。例えば
uri: 'http://ヰキサイト.npn/api.php'
のように記す。
localsettings.js を設定する。(これは必要ないかな)
cp localsettings.example.js localsettings.js vim localsettings.js
次の部分を編集する。
exports.setup = function(parsoidConfig) {
// Do something dynamic with `parsoidConfig` like,
parsoidConfig.setMwApi({
uri: 'http://mywiki.npn/api.php',
});
};
/etc/hosts を編集する。
nano /etc/hosts 192.168.33.10 mywiki.npn
Windows 10 のhosts ファイルも同様に編集すると、Windows のブラウザでアクセスできる。
C:\Windows\System32\drivers\etc\hosts
次に、再起動時に 起動するように parsoid.service を設定する
cd /etc/systemd/system/ nano parsoid.service
次の通り貼り付ける。
[Unit] Description=Mediawiki Parsoid web service on node.js Documentation=http://www.mediawiki.org/wiki/Parsoid Wants=local-fs.target network.target After=local-fs.target network.target [Install] WantedBy=multi-user.target [Service] Type=simple User=root Group=root WorkingDirectory=/opt/parsoid ExecStart=/usr/bin/node /opt/parsoid/bin/server.js KillMode=process Restart=on-success PrivateTmp=true StandardOutput=syslog
Parsoid service を起動する。
systemctl daemon-reload
systemctl start parsoid
systemctl enable parsoid
Parsoid の起動確認。
netstat -plntu
次のような行があれば正常に起動している。
tcp6 0 0 :::8000 :::* LISTEN 981/node
6.VisualEditor 本体をインストールする。
必ずしも最新版が動くとは限らない。それで嵌まるので注意。
MediaWiki のバージョンに合わせて、適合するバージョンのVisualEditor extension を選択せねばならぬ。
ここから取得するのが確実。
cd /home/kusanagi/mywiki/DocumentRoot/extensions
wget https://extdist.wmflabs.org/dist/extensions/VisualEditor-REL1_31-13a585a.tar.gz
tar -xzf VisualEditor-REL1_31-13a585a.tar.gz
cd ../
nano LocalSettings.php
LocalSettings.php に次を追加する。
wfLoadExtension( 'VisualEditor' ); // Enable by default for everybody $wgDefaultUserOptions['visualeditor-enable'] = 1; // Optional: Set VisualEditor as the default for anonymous users // otherwise they will have to switch to VE // $wgDefaultUserOptions['visualeditor-editor'] = "visualeditor"; // Don't allow users to disable it $wgHiddenPrefs[] = 'visualeditor-enable'; $wgVirtualRestConfig['modules']['parsoid'] = array( // URL to the Parsoid instance // Use port 8142 if you use the Debian package 'url' => 'http://mywiki.npn:8000', // Parsoid "domain", see below (optional) 'domain' => 'mywiki.npn', // Parsoid "prefix", see below (optional) 'prefix' => 'mywiki.npn' );
全ファイルのオーナーを nginx:nginx に変更統一する。叉は kusanagi.kusanagi
chown -R kusanagi.kusanagi /home/kusanagi/mywiki/DocumentRoot
テスト
あらためて http://mywiki.npn/
を開いてみる。
今の所、LocalSettings.php はこんな感じ。
<?php # This file was automatically generated by the MediaWiki 1.31.0 # installer. If you make manual changes, please keep track in case you # need to recreate them later. # # See includes/DefaultSettings.php for all configurable settings # and their default values, but don't forget to make changes in _this_ # file, not there. # # Further documentation for configuration settings may be found at: # https://www.mediawiki.org/wiki/Manual:Configuration_settings # Protect against web entry if ( !defined( 'MEDIAWIKI' ) ) { exit; } ## Uncomment this to disable output compression # $wgDisableOutputCompression = true; $wgSitename = "mywiki"; ## The URL base path to the directory containing the wiki; ## defaults for all runtime URL paths are based off of this. ## For more information on customizing the URLs ## (like /w/index.php/Page_title to /wiki/Page_title) please see: ## https://www.mediawiki.org/wiki/Manual:Short_URL $wgScriptPath = ""; ## The protocol and server name to use in fully-qualified URLs $wgServer = "http://mywiki.npn"; ## The URL path to static resources (images, scripts, etc.) $wgResourceBasePath = $wgScriptPath; ## The URL path to the logo. Make sure you change this from the default, ## or else you'll overwrite your logo when you upgrade! $wgLogo = "$wgResourceBasePath/resources/assets/daia.jpg"; ## UPO means: this is also a user preference option $wgEnableEmail = true; $wgEnableUserEmail = true; # UPO $wgEmergencyContact = "mywiki@mywiki.npn"; $wgPasswordSender = "mywiki@mywiki.npn"; $wgEnotifUserTalk = true; # UPO $wgEnotifWatchlist = true; # UPO $wgEmailAuthentication = true; ## Database settings $wgDBtype = "mysql"; $wgDBserver = "localhost"; $wgDBname = "enwiki2"; $wgDBuser = "mywiki"; $wgDBpassword = "mypasswdaaa"; # MySQL specific settings $wgDBprefix = ""; # MySQL table options to use during installation or update $wgDBTableOptions = "ENGINE=InnoDB, DEFAULT CHARSET=binary"; ## Shared memory settings $wgMainCacheType = CACHE_ACCEL; $wgMemCachedServers = []; ## To enable image uploads, make sure the 'images' directory ## is writable, then set this to true: $wgEnableUploads = true; $wgUseImageMagick = true; $wgImageMagickConvertCommand = "/usr/bin/convert"; # InstantCommons allows wiki to use images from https://commons.wikimedia.org $wgUseInstantCommons = true; # Periodically send a pingback to https://www.mediawiki.org/ with basic data # about this MediaWiki instance. The Wikimedia Foundation shares this data # with MediaWiki developers to help guide future development efforts. $wgPingback = false; ## If you use ImageMagick (or any other shell command) on a ## Linux server, this will need to be set to the name of an ## available UTF-8 locale $wgShellLocale = "en_US.utf8"; ## Set $wgCacheDirectory to a writable directory on the web server ## to make your wiki go slightly faster. The directory should not ## be publically accessible from the web. $wgCacheDirectory = "$IP/cache"; $wgUseFileCache = true; $wgFileCacheDirectory = "$IP/cache"; $wgUseLocalMessageCache = true; $wgCacheDirectory = '$IP/cache'; $wgJobRunRate = 0.01; $wgUseGzip = true; $wgEnableSidebarCache = true; $wgResourceLoaderMaxage = array( 'versioned' => array( // Squid/Varnish but also any other public proxy cache between the client and MediaWiki 'server' => 30 * 24 * 60 * 60, // 30 days // On the client side (e.g. in the browser cache). 'client' => 30 * 24 * 60 * 60, // 30 days ), 'unversioned' => array( 'server' => 30 * 24 * 60 * 60, // 30 days 'client' => 30 * 24 * 60 * 60, // 30 days ), ); #開発時にキャッシュを無効にする #$wgCachePages = false; #$wgCacheEpoch = 'date +%Y%m%d%H%M%S'; # Site language code, should be one of the list in ./languages/data/Names.php $wgLanguageCode = "ja"; $wgSecretKey = "3f1f2d6b93af7d3e8cc21a6b5c3eb29483db2919dfd170afc36d661a8018c7e4"; # Changing this will log out all existing sessions. $wgAuthenticationTokenVersion = "1"; # Site upgrade key. Must be set to a string (default provided) to turn on the # web installer while LocalSettings.php is in place $wgUpgradeKey = "be5785e104b6d206"; ## For attaching licensing metadata to pages, and displaying an ## appropriate copyright notice / icon. GNU Free Documentation ## License and Creative Commons licenses are supported so far. $wgRightsPage = ""; # Set to the title of a wiki page that describes your license/copyright $wgRightsUrl = "https://creativecommons.org/licenses/by-nc-sa/4.0/"; $wgRightsText = "クリエイティブ・コモンズ 表示-非営利-継承"; $wgRightsIcon = "$wgResourceBasePath/resources/assets/licenses/cc-by-nc-sa.png"; # Path to the GNU diff3 utility. Used for conflict resolution. $wgDiff3 = "/usr/bin/diff3"; # The following permissions were set based on your choice in the installer $wgGroupPermissions['*']['edit'] = true; ## Default skin: you can change the default skin. Use the internal symbolic ## names, ie 'vector', 'monobook': #if (preg_match("/(mobile|webos|opera mini)/i", $_SERVER['HTTP_USER_AGENT'])) { # $wgDefaultSkin = 'wptouch'; #} else { $wgDefaultSkin = 'vector'; #} # Enabled skins. # The following skins were automatically enabled: require_once "$IP/skins/cavendishmw/cavendishmw.php"; #wfLoadSkin( 'cavendishmw' ); wfLoadSkin( 'MonoBook' ); wfLoadSkin( 'Timeless' ); wfLoadSkin( 'Vector' ); #wfLoadSkin( ‘WPtouch); # Enabled extensions. Most of the extensions are enabled by adding # wfLoadExtensions('ExtensionName'); # to LocalSettings.php. Check specific extension documentation for more details. # The following extensions were automatically enabled: wfLoadExtension( 'CategoryTree' ); wfLoadExtension( 'CheckUser' ); wfLoadExtension( 'Cite' ); wfLoadExtension( 'CiteThisPage' ); wfLoadExtension( 'ConfirmEdit' ); wfLoadExtension( 'Description2' ); wfLoadExtension( 'Gadgets' ); require_once "$IP/extensions/googleAnalytics/googleAnalytics.php"; require_once "$IP/extensions/HTMLets/HTMLets.php"; wfLoadExtension( 'ImageMap' ); wfLoadExtension( 'InputBox' ); wfLoadExtension( 'intersection' ); wfLoadExtension( 'Interwiki' ); #wfLoadExtension( 'LinkTitles' ); wfLoadExtension( 'LocalisationUpdate' ); wfLoadExtension( 'Lockdown' ); wfLoadExtension( 'Math' ); wfLoadExtension( 'MsCatSelect' ); wfLoadExtension( 'MultimediaViewer' ); wfLoadExtension( 'OATHAuth' ); wfLoadExtension( 'ParserFunctions' ); wfLoadExtension( 'PdfHandler' ); wfLoadExtension( 'Poem' ); wfLoadExtension( 'Renameuser' ); wfLoadExtension( 'ReplaceText' ); wfLoadExtension( 'SpamBlacklist' ); wfLoadExtension( 'SyntaxHighlight_GeSHi' ); wfLoadExtension( 'TitleBlacklist' ); #wfLoadExtension( 'VisualEditor' ); wfLoadExtension( 'WikiEditor' ); wfLoadExtension( 'Scribunto' ); $wgScribuntoDefaultEngine = 'luastandalone'; wfLoadExtension( 'MassMessage' ); # End of automatically generated settings. # Add more configuration options below. $wgNamespacesWithSubpages[NS_MAIN] = 1; #$wgLinkTitlesParseOnEdit = false; // 編集時に解析しない #$wgLinkTitlesParseOnRender = true; // ページを表示したときに解析する #$wgLinkTitlesFirstOnly = false; // リンク付けは1つだけ #// 最初に見つけたワードにリンク付け #$wgLinkTitlesWordStartOnly = false; // ワードの始めは区切り文字が必要 #$wgLinkTitlesWordEndOnly = false; // ワードの最後は区切り文字が必要 #$wgLinkTitlesMinimumTitleLength = 1; #$wgLinkTitlesSmartMode = true; wfLoadExtension( 'VisualEditor' ); // Enable by default for everybody $wgDefaultUserOptions['visualeditor-enable'] = 1; // Optional: Set VisualEditor as the default for anonymous users // otherwise they will have to switch to VE // $wgDefaultUserOptions['visualeditor-editor'] = "visualeditor"; // Don't allow users to disable it $wgHiddenPrefs[] = 'visualeditor-enable'; // OPTIONAL: Enable VisualEditor's experimental code features #$wgDefaultUserOptions['visualeditor-enable-experimental'] = 1; $wgVirtualRestConfig['modules']['parsoid'] = array( // URL to the Parsoid instance // Use port 8142 if you use the Debian package 'url' => 'http://mywiki.npn:8000', // Parsoid "domain", see below (optional) 'domain' => 'mywiki.npn', // Parsoid "prefix", see below (optional) 'prefix' => 'mywiki.npn' ); $wgShowExceptionDetails = true; $wgShowDBErrorBacktrace = true; $wgFileExtensions[] = 'svg'; $wgAllowTitlesInSVG = true; $wgSVGConverter = 'rsvg'; $wgMaxShellMemory = 819200; $wgMaxImageArea = 5e7;
Vagrant Kusanagi の容量を40GBから100GB に増量する
日本語版 Wikipedia のデータを全部取り込もうとするならば、ディスク容量は100GB以上は必要になる。
初期設定では40GBしかないので、これを最初から100GBに拡張しておく。ここでも嵌る。
まず、vmdk形式 から vdi形式にクローンする。
このサイトに準じて進める。
次に、だいたい次のようなコマンドで拡張完了。
1438 l /dev/mapper/cl-root 1439 fdisk -l 1448 fdisk /dev/sda 1450 cat /etc/fstab 1471 lsblk 1472 df 1473 fdisk -l /dev/sda 1474 parted /dev/sda 1476 pvresize /dev/sda2 reboot 1477 pvs 1478 vgs 1479 lvs 1481 l /dev/cl/root 1482 lvextend -l +100%FREE /dev/cl/root 1483 lvdisplay -C 1484 lvs 1487 xfs_growfs /dev/mapper/cl-root
現在の状況。95GBになっている。
root@ # df ファイルシス タイプ サイズ 使用 残り 使用% マウント位置 /dev/mapper/cl-root xfs 95G 82G 14G 86% / devtmpfs devtmpfs 2.4G 0 2.4G 0% /dev tmpfs tmpfs 2.5G 0 2.5G 0% /dev/shm tmpfs tmpfs 2.5G 8.6M 2.4G 1% /run tmpfs tmpfs 2.5G 0 2.5G 0% /sys/fs/cgroup /dev/sda1 xfs 1014M 194M 821M 20% /boot tmpfs tmpfs 493M 0 493M 0% /run/user/0
Mediawiki に Wikipedia のデータを取り込む
7. ヰキペディアのデータをダウンロード
8.MWDumper のインストール
git clone https://phabricator.wikimedia.org/diffusion/MWDU/mwdumper.git
cd mwdumper
mvn compile
mvn package
9.データのインポート
そして
にある、このスクリプトの通りにするとよい。
コマンドラインで次々にコピペ 実行していけばよい。
# Dump SQL to disk in even sized chunks. This takes about 80 Gb of hard drive space and 3 hours for enwiki. # Setup the db to receive the chunks. This takes a few seconds. # Import the chunks. This takes a few days for enwiki. # Rebuild the DB. This takes another day for enwiki. # Run standard post import cleanup. I haven't finished this step successfully yet but some of it can be skipped I think. export DUMP_PREFIX=/public/datasets/public/enwiki/20130604/jawiki-20180720 export DIR_ROOT=/data/project/dump export DIR=${DIR_ROOT}/enwiki export EXPORT_PROCESSES=4 export IMPORT_PROCESSES=4 export DB=enwiki2 export EXPORT_FILE_SIZE=5 export EXPORT_FILE_SUFFIX_LENGTH=8 export LOG=~/log bash -c 'sleep 1 && echo y' | mysqladmin drop ${DB} -u root sudo rm -rf ${DIR} rm -rf ${LOG} sudo mkdir -p ${DIR} sudo chown -R ${USER} ${DIR_ROOT} mkdir -p ${LOG} # Setup the db to receive the chunks. mysqladmin create ${DB} --default-character-set=utf8 -u root mysql -u root ${DB} < /srv/mediawiki/maintenance/tables.sql mysql -u root ${DB} <<HERE ALTER TABLE page CHANGE page_id page_id INTEGER UNSIGNED, DROP INDEX name_title, DROP INDEX page_random, DROP INDEX page_len, DROP INDEX page_redirect_namespace_len; ALTER TABLE revision CHANGE rev_id rev_id INTEGER UNSIGNED, DROP INDEX rev_page_id, DROP INDEX rev_timestamp, DROP INDEX page_timestamp, DROP INDEX user_timestamp, DROP INDEX usertext_timestamp, DROP INDEX page_user_timestamp; ALTER TABLE text CHANGE old_id old_id INTEGER UNSIGNED; HERE
そして、いよいよ巨大なデータをインポートするコマンドは:
java -server -classpath /home/kusanagi/mywiki/mwdumper/target/mwdumper-1.25.jar org.mediawiki.dumper.Dumper --output=mysql://localhost/enwiki2?user=root\&password=mypasswdxxx\&characterEncoding=UTF8 --format=sql:1.25 /home/kusanagi/mywiki/DocumentRoot/jawiki-20180720-pages-articles.xml.bz2
Mysql の設定ファイル編集
これでエラーで失敗停止する場合は、 mysql の設定ファイルを次のように編集するとよい。
大型のデータを高速にインポートでいるように最適化。
Webmin で編集できる。
/etc/my.cnf.d/server.cnf
## /etc/my.cnf.d/server.cnf [server] # this is only for the mysqld standalone daemon [mysqld] server-id = 1 sql_mode=ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION character_set_server = utf8mb4 skip-character-set-client-handshake max_connections = 900 thread_cache_size = 300 table_cache = 256 max_allowed_packet = 512M query_cache_size = 128M tmp_table_size = 32M max_heap_table_size = 32M thread_stack = 512K wait_timeout = 31536000 key_buffer = 384M sort_buffer_size = 256M read_buffer_size = 256M read_rnd_buffer_size = 256M myisam_sort_buffer_size = 256M open_files_limit = 100000 innodb_buffer_pool_size = 2G #innodb_additional_mem_pool_size = 20M # Set .._log_file_size to 25 % of buffer pool size innodb_log_file_size = 512M innodb_log_buffer_size = 32M innodb_lock_wait_timeout = 50 # 50 default # create a sepparate file for each InnoDB table #innodb_file_format = Barracuda #Removed: MariaDB 10.3.1 Default :Barracuda innodb_file_per_table = 1 #innodb_large_prefix #Removed: MariaDB 10.3.1 Default ON (>= MariaDB 10.2.2) innodb_flush_log_at_trx_commit = 2 #データの初期インポート時のみ skip_innodb_doublewrite #データの初期インポート時のみ log-error = /var/log/mysql/mysqld.log log-warnings = 1 slow_query_log = 1 slow_query_log_file = "/var/log/mysql/slow.log" long_query_time = 5 # # * Galera-related settings # [galera] # Mandatory settings #wsrep_on=ON #wsrep_provider= #wsrep_cluster_address= #binlog_format=row #default_storage_engine=InnoDB #innodb_autoinc_lock_mode=2 # # Allow server to accept connections on all interfaces. # #bind-address=0.0.0.0 # # Optional setting #wsrep_slave_threads=1 #innodb_flush_log_at_trx_commit=0 # this is only for embedded server [embedded] # This group is only read by MariaDB servers, not by MySQL. # If you use the same .cnf file for MySQL and MariaDB, # you can put MariaDB-only options here [mariadb] # This group is only read by MariaDB-10.3 servers. # If you use the same .cnf file for MariaDB of different versions, # use this group for options that older servers don't understand [mariadb-10.3] [myisamchk] key_buffer = 256M sort_buffer_size = 256M read_buffer = 256M write_buffer = 256M [mysqlhotcopy] interactive-timeout [mysqldump] max_allowed_packet=512M
/etc/my.cnf.d/mysql-clients.cnf を編集する。
#/etc/my.cnf.d/mysql-clients.cnf # These groups are read by MariaDB command-line tools # Use it for options that affect only one utility # [mysql] default-character-set = utf8mb4 no-auto-rehash [mysql_upgrade] [mysqladmin] [mysqlbinlog] [mysqlcheck] [mysqldump] quick max_allowed_packet = 1000M [mysqlimport] [mysqlshow] [mysqlslap]
これ以降はする必要があるのかよくわからない。
# Rebuild the DB mysql -u root ${DB} <<HERE CREATE TABLE bad_page AS SELECT page_namespace, page_title, COUNT(*) AS count FROM page GROUP BY page_namespace, page_title HAVING count > 1; UPDATE page, bad_page SET page.page_title = CONCAT(page.page_title, page.page_id) WHERE page.page_namespace = bad_page.page_namespace AND page.page_title = bad_page.page_title; DROP TABLE bad_page; ALTER TABLE page CHANGE page_id page_id INTEGER UNSIGNED AUTO_INCREMENT, ADD UNIQUE INDEX name_title (page_namespace,page_title), ADD INDEX page_random (page_random), ADD INDEX page_len (page_len), ADD INDEX page_redirect_namespace_len (page_is_redirect, page_namespace, page_len); ALTER TABLE revision CHANGE rev_id rev_id INTEGER UNSIGNED AUTO_INCREMENT, ADD UNIQUE INDEX rev_page_id (rev_page, rev_id), ADD INDEX rev_timestamp (rev_timestamp), ADD INDEX page_timestamp (rev_page,rev_timestamp), ADD INDEX user_timestamp (rev_user,rev_timestamp), ADD INDEX usertext_timestamp (rev_user_text,rev_timestamp), ADD INDEX page_user_timestamp (rev_page,rev_user,rev_timestamp); ALTER TABLE text CHANGE old_id old_id INTEGER UNSIGNED AUTO_INCREMENT; HERE # Run standard post import cleanup cd /srv/mediawiki php maintenance/update.php
このサイトにあるように
(このサイトのコマンドをコピペすると、記号に全角文字が混じっていてエラーになるので注意 - ー ' ’ など)
Using mwdumper
mwdumper is a Java application that can be used to read, write and convert MediaWiki XML dumps. It can be used to generate a SQL dump from the XML file (for later use with mysql or phpmyadmin) as well as for importing into the database directly. It is a lot faster than importDump.php, however, it only imports the revisions (page contents), and does not update the internal link tables accordingly -- that means that category pages and many special pages will show incomplete or incorrect information unless you update those tables.If available, you can fill the link tables by importing separate SQL dumps of these tables using the mysql command line client directly. For Wikimedia wikis, this data is available along with the XML dumps.
Otherwise, you can run rebuildall.php, which will take a long time, because it has to parse all pages. This is not recommended for large data sets.
検索エンジンのインデックスを構築するコマンドをすると、途中で止まってしまった。
$ php <Root directory of MediaWiki>/maintenance/rebuildall.php −−conf <Root directory ofMediaWiki>/LocalSettings.php
こんなエラーログで止まる。mysql の設定ファイルをいじって何度やっても同じエラー
Rebuilding index fields for 3816530 pages... .... 1910000 1910500 1911000 PHP Warning: mysqli::query(): MySQL server has gone away in /home/kusanagi/mywiki/DocumentRoot/includes/libs/rdbms/database/DatabaseMysqli.php on line 46 PHP Warning: mysqli::query(): Error reading result set's header in /home/kusanagi/mywiki/DocumentRoot/includes/libs/rdbms/database/DatabaseMysqli.php on line 46 [d01b2eff089723d495246bb9] [no req] Wikimedia\Rdbms\DBQueryError from line 1457 of /home/kusanagi/mywiki/DocumentRoot/includes/libs/rdbms/database/Database.php: A connection error occured. Query: SELECT rev_id,rev_page,rev_text_id,rev_timestamp,rev_minor_edit,rev_deleted,rev_len,rev_parent_id,rev_sha1,rev_comment AS `rev_comment_text`,NULL AS `rev_comment_data`,NULL AS `rev_comment_cid`,rev_user,rev_user_text,NULL AS `rev_actor`,rev_content_format,rev_content_model,page_namespace,page_title,page_id,page_latest,page_is_redirect,page_len,old_text,old_flags FROM `revision`,`page`,`text` WHERE (page_id BETWEEN 1911000 AND 1911499) AND (page_latest = rev_id) AND (rev_text_id = old_id) Function: RebuildTextIndex::populateSearchIndex Error: 2006 MySQL server has gone away (localhost) Backtrace: #0 /home/kusanagi/mywiki/DocumentRoot/includes/libs/rdbms/database/Database.php(1427): Wikimedia\Rdbms\Database->makeQueryException(string, integer, string, string) #1 /home/kusanagi/mywiki/DocumentRoot/includes/libs/rdbms/database/Database.php(1200): Wikimedia\Rdbms\Database->reportQueryError(string, integer, string, string, boolean) #2 /home/kusanagi/mywiki/DocumentRoot/includes/libs/rdbms/database/Database.php(1653): Wikimedia\Rdbms\Database->query(string, string) #3 /home/kusanagi/mywiki/DocumentRoot/maintenance/rebuildtextindex.php(106): Wikimedia\Rdbms\Database->select(array, array, array, string) #4 /home/kusanagi/mywiki/DocumentRoot/maintenance/rebuildtextindex.php(76): RebuildTextIndex->populateSearchIndex() #5 /home/kusanagi/mywiki/DocumentRoot/maintenance/rebuildall.php(48): RebuildTextIndex->execute() #6 /home/kusanagi/mywiki/DocumentRoot/maintenance/doMaintenance.php(94): RebuildAll->execute() #7 /home/kusanagi/mywiki/DocumentRoot/maintenance/rebuildall.php(67): require_once(string) #8 {main}
このエラーの原因を特定する。
これは rebuildtextindex-2.php というファイル を作って、500 単位ではなく、1 個ずつ処理するようにすると、どこでエラーが発生しているのか特定できる。
<?php
require_once __DIR__ . '/Maintenance.php';
use Wikimedia\Rdbms\IMaintainableDatabase;
use Wikimedia\Rdbms\DatabaseSqlite;
/**
* Maintenance script that rebuilds search index table from scratch.
*
* @ingroup Maintenance
*/
class RebuildTextIndex extends Maintenance {
const RTI_CHUNK_SIZE = 1;
/**
* @var IMaintainableDatabase
*/
private $db;
public function __construct() {
parent::__construct();
$this->addDescription( 'Rebuild search index table from scratch' );
}
public function getDbType() {
return Maintenance::DB_ADMIN;
}
public function execute() {
// Shouldn't be needed for Postgres
$this->db = $this->getDB( DB_MASTER );
if ( $this->db->getType() == 'postgres' ) {
$this->fatalError( "This script is not needed when using Postgres.\n" );
}
if ( $this->db->getType() == 'sqlite' ) {
if ( !DatabaseSqlite::getFulltextSearchModule() ) {
$this->fatalError( "Your version of SQLite module for PHP doesn't "
. "support full-text search (FTS3).\n" );
}
if ( !$this->db->checkForEnabledSearch() ) {
$this->fatalError( "Your database schema is not configured for "
. "full-text search support. Run update.php.\n" );
}
}
if ( $this->db->getType() == 'mysql' ) {
// $this->dropMysqlTextIndex();
// $this->clearSearchIndex();
$this->populateSearchIndex();
// $this->createMysqlTextIndex();
} else {
// $this->clearSearchIndex();
$this->populateSearchIndex();
}
$this->output( "Done.\n" );
}
/**
* Populates the search index with content from all pages
*/
protected function populateSearchIndex() {
$res = $this->db->select( 'page', 'MAX(page_id) AS count' );
$s = $this->db->fetchObject( $res );
$count = $s->count;
$this->output( "Rebuilding index fields for {$count} pages...\n" );
$n = 1911000;
$revQuery = Revision::getQueryInfo( [ 'page', 'text' ] );
while ( $n < $count ) {
if ( $n ) {
$this->output( $n . "\n" );
}
$end = $n + self::RTI_CHUNK_SIZE - 1;
$res = $this->db->select( $revQuery['tables'], $revQuery['fields'],
[ "page_id BETWEEN $n AND $end", 'page_latest = rev_id', 'rev_text_id = old_id' ],
__METHOD__
);
foreach ( $res as $s ) {
$title = Title::makeTitle( $s->page_namespace, $s->page_title );
try {
$rev = new Revision( $s );
$content = $rev->getContent();
$u = new SearchUpdate( $s->page_id, $title, $content );
$u->doUpdate();
} catch ( MWContentSerializationException $ex ) {
$this->output( "Failed to deserialize content of revision {$s->rev_id} of page "
. "`" . $title->getPrefixedDBkey() . "`!\n" );
}
}
$n += self::RTI_CHUNK_SIZE;
}
}
/**
* (MySQL only) Drops fulltext index before populating the table.
*/
private function dropMysqlTextIndex() {
$searchindex = $this->db->tableName( 'searchindex' );
if ( $this->db->indexExists( 'searchindex', 'si_title', __METHOD__ ) ) {
$this->output( "Dropping index...\n" );
$sql = "ALTER TABLE $searchindex DROP INDEX si_title, DROP INDEX si_text";
$this->db->query( $sql, __METHOD__ );
}
}
/**
* (MySQL only) Adds back fulltext index after populating the table.
*/
private function createMysqlTextIndex() {
$searchindex = $this->db->tableName( 'searchindex' );
$this->output( "\nRebuild the index...\n" );
foreach ( [ 'si_title', 'si_text' ] as $field ) {
$sql = "ALTER TABLE $searchindex ADD FULLTEXT $field ($field)";
$this->db->query( $sql, __METHOD__ );
}
}
/**
* Deletes everything from search index.
*/
private function clearSearchIndex() {
$this->output( 'Clearing searchindex table...' );
$this->db->delete( 'searchindex', '*', __METHOD__ );
$this->output( "Done\n" );
}
}
$maintClass = RebuildTextIndex::class;
require_once RUN_MAINTENANCE_IF_MAIN;
php rebuildtextindex-2.php
page というテーブルの page_id 1911451 からエラーが発生していることが判明するので、このカラム行を削除する。
「スイーツ(笑) 」というタイトルの記事だった。これを削除する。
DELETE FROM `page` WHERE `page`.`page_id` = 1911451
phpMyAdmin で操作してもよい。
これでエラーがなくなって最後まで行けた。
phpMyAdmin のインストール
ここで phpMyAdmin を yum インストールしようとしたがエラーで進まなかった。
次の方法でやっとインストールできた。
1789 git clone https://github.com/phpmyadmin/phpmyadmin.git cd phpmyadmin 1790 composer update // composer が見つからないので新規インストールする。 1791 php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 1792 php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" 1794 php -r "unlink('composer-setup.php');" 1804 php composer-setup.php --install-dir=/usr/bin --filename=composer 1805 updatedb 1809 cd phpmyadmin 1810 composer update 1812 composer create-project phpmyadmin/phpmyadmin mv ./phpmyadmin /home/kusanagi/mywiki/DocumentRoot/
これでヱブでアクセスできるようになる。
cd /home/kusanagi/mywiki/DocumentRoot/phpmyadmin cp -af config.sample.inc.php config.inc.php nano config.inc.php
config.inc.php を編集する。
ブラウザーで mywiki.npn/phpmyadmin/setup/
にアクセスし、設定ファイルを作成後、ダウンロードし、 config.inc.php にペーストする。
sql ファイルをインポート
次に、その他のテーブルのデータ、 sql ファイルをダウンロードしてインポート。
sql.gz を解凍。
gunzip ********.sql.gz
mysql -u root -pmypasswd enwiki2 < jawiki-20180720-category.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-categorylinks.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-change_tag.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-externallinks.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-image.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-imagelinks.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-iwlinks.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-langlinks.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-page_props.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-page_restrictions.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-pagelinks.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-protected_titles.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-templatelinks.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-wbc_entity_usage.sql mysql -u root -pmypasswd enwiki2 < jawiki-20180720-geo_tags.sql
pagelinks.sql のインポートに時間がかかる。24時間以上。
こんな感じになった。
メディアヰキに特権ユーザーを追加する
このやり方だと、データーベースはまっさらな状態から築き上げるので、まだ管理者ユーザーは追加されていない状態である。
https://mywiki.npn/index.php?title=特別:アカウント作成
から第一号のアカウントを作ると、普通のユーザーになり、管理者特権はない。他のユーザーの権限を変更したりすることはできない。
そこで、LocalSettings.php に次の行を一時的に追加して、ログインしたユーザーならば誰でも管理者特権を得られるようにする。
// Implicit group for all logged-in accounts $wgGroupPermissions['user']['move'] = true; $wgGroupPermissions['user']['move-subpages'] = true; $wgGroupPermissions['user']['move-rootuserpages'] = true; // can move root userpages $wgGroupPermissions['user']['move-categorypages'] = true; $wgGroupPermissions['user']['movefile'] = true; $wgGroupPermissions['user']['read'] = true; $wgGroupPermissions['user']['edit'] = true; $wgGroupPermissions['user']['createpage'] = true; $wgGroupPermissions['user']['createtalk'] = true; $wgGroupPermissions['user']['writeapi'] = true; $wgGroupPermissions['user']['upload'] = true; $wgGroupPermissions['user']['reupload'] = true; $wgGroupPermissions['user']['reupload-shared'] = true; $wgGroupPermissions['user']['minoredit'] = true; $wgGroupPermissions['user']['editmyusercss'] = true; $wgGroupPermissions['user']['editmyuserjson'] = true; $wgGroupPermissions['user']['editmyuserjs'] = true; $wgGroupPermissions['user']['purge'] = true; $wgGroupPermissions['user']['sendemail'] = true; $wgGroupPermissions['user']['applychangetags'] = true; $wgGroupPermissions['user']['changetags'] = true; $wgGroupPermissions['user']['editcontentmodel'] = true; // Implicit group for accounts that pass $wgAutoConfirmAge $wgGroupPermissions['user']['autoconfirmed'] = true; $wgGroupPermissions['user']['editsemiprotected'] = true; // Users with bot privilege can have their edits hidden // from various log pages by default $wgGroupPermissions['user']['bot'] = true; $wgGroupPermissions['user']['autoconfirmed'] = true; $wgGroupPermissions['user']['editsemiprotected'] = true; $wgGroupPermissions['user']['nominornewtalk'] = true; $wgGroupPermissions['user']['autopatrol'] = true; $wgGroupPermissions['user']['suppressredirect'] = true; $wgGroupPermissions['user']['apihighlimits'] = true; $wgGroupPermissions['user']['writeapi'] = true; // Most extra permission abilities go to this group $wgGroupPermissions['user']['block'] = true; $wgGroupPermissions['user']['createaccount'] = true; $wgGroupPermissions['user']['delete'] = true; // can be separately configured for pages with > $wgDeleteRevisionsLimit revs $wgGroupPermissions['user']['bigdelete'] = true; // can view deleted history entries, but not see or restore the text $wgGroupPermissions['user']['deletedhistory'] = true; // can view deleted revision text $wgGroupPermissions['user']['deletedtext'] = true; $wgGroupPermissions['user']['undelete'] = true; $wgGroupPermissions['user']['editinterface'] = true; $wgGroupPermissions['user']['editusercss'] = true; $wgGroupPermissions['user']['edituserjson'] = true; $wgGroupPermissions['user']['edituserjs'] = true; $wgGroupPermissions['user']['import'] = true; $wgGroupPermissions['user']['importupload'] = true; $wgGroupPermissions['user']['move'] = true; $wgGroupPermissions['user']['move-subpages'] = true; $wgGroupPermissions['user']['move-rootuserpages'] = true; $wgGroupPermissions['user']['move-categorypages'] = true; $wgGroupPermissions['user']['patrol'] = true; $wgGroupPermissions['user']['autopatrol'] = true; $wgGroupPermissions['user']['protect'] = true; $wgGroupPermissions['user']['editprotected'] = true; $wgGroupPermissions['user']['rollback'] = true; $wgGroupPermissions['user']['upload'] = true; $wgGroupPermissions['user']['reupload'] = true; $wgGroupPermissions['user']['reupload-shared'] = true; $wgGroupPermissions['user']['unwatchedpages'] = true; $wgGroupPermissions['user']['autoconfirmed'] = true; $wgGroupPermissions['user']['editsemiprotected'] = true; $wgGroupPermissions['user']['ipblock-exempt'] = true; $wgGroupPermissions['user']['blockemail'] = true; $wgGroupPermissions['user']['markbotedits'] = true; $wgGroupPermissions['user']['apihighlimits'] = true; $wgGroupPermissions['user']['browsearchive'] = true; $wgGroupPermissions['user']['noratelimit'] = true; $wgGroupPermissions['user']['movefile'] = true; $wgGroupPermissions['user']['unblockself'] = true; $wgGroupPermissions['user']['suppressredirect'] = true; # $wgGroupPermissions['user']['pagelang'] = true; # $wgGroupPermissions['user']['upload_by_url'] = true; $wgGroupPermissions['user']['mergehistory'] = true; $wgGroupPermissions['user']['managechangetags'] = true; $wgGroupPermissions['user']['deletechangetags'] = true; // Permission to change users' group assignments $wgGroupPermissions['user']['userrights'] = true; $wgGroupPermissions['user']['noratelimit'] = true;
すぐに設定が反映されなかったら、再起動してみるのも良い。
https://mywiki.npn/index.php/特別:利用者権限
にアクセスし、既に作成したユーザー名を入力する。
そして、すべてのグループに所属チェックして保存する。
特権ユーザーに変身できたことを確認したら、LocalSettings.php から追加した行を削除しておく。
Special:NewItem
データー充満で新システムに移行
検索が遅いので Elasticsearch を導入しようとして、インデックスの構築を始めたら100GBのディスク容量が一杯になって停止した。
それで再デスク容量の増加作業を兼ねて、Windows ノート PC 本体の500GBディスクを分割し、Linux デスクトップをインストールした。
約350GB を丸ごと開発環境として使えるようにする。
Linux デスクトップに移行中。
今後の課題
Wikipedia で使用されている Extensions をすべて追加して、少なくとも表示エラーが出ないようにする。
検索の高速化。 Mroonga か Elasticsearch か。
どのようなモジュール、拡張機能がインストールされているかはここでわかる。