Ломаем WD MyCloud gen2.

Сегодня мы будем автоматически запускать разного рода приложения после перезапуска системы на сетевом HDD WesternDigital MyCloud второго поколения.

Мне нужно систематически сливать информацию с удалённого хранилища на упомянутом выше девайсе на свой домашний сервер. Можно, конечно, делать это через FTP, поддерживаемый этой железякой из коробки, но мы не ищем лёгких путей… Особенно, когда есть ssh доступ к испытуемому агрегату. 

Итак. Я выбрал в качестве решения моей задачи rsync и всё было бы замечательно, если бы не одно «но» — во втором поколении WD MyCloud корневая файловая система при загрузке разворачивается из образа в ram диск и при ребуте, соответственно, все внесённые изменения отправляются в /dev/ass.

root@xxx-d root # mount
%root% on / type unknown (rw)
proc on /proc type proc (rw)
/dev/ram0 on / type ext2 (rw)
sysfs on /sys type sysfs (defaults)
mdev on /dev type tmpfs (defaults)
proc on /proc type proc (0)
cgroup on /sys/fs/cgroup type cgroup (rw,memory,cpu)
/dev/sda3 on /boot type ext4 (rw)
/dev/sda7 on /usr/local/config type ext4 (rw)
/dev/loop0 on /usr/local/modules type squashfs (loop)
tmpfs on /mnt type tmpfs (size=1m,nr_inodes=0)
tmpfs on /var/log type tmpfs (size=40m,nr_inodes=0)
tmpfs on /tmp type tmpfs (size=100m,nr_inodes=20000)
/dev/sda4 on /mnt/HD_a4 type ext4 (rw)
/dev/sda2 on /mnt/HD/HD_a2 type ext4 (rw,noatime,nodiratime,barrier=0,usrquota,grpquota)
nfsd on /proc/fs/nfsd type nfsd (rw)
root@xxx-d root #

В буржуйских интернетах люди пошли по пути изменения и пересборки образа, из которого разворачивается система, но этот подход мне не по сердцу, ибо после обновления фирмвари все наши плюшки протеряются и придётся опять пересобирать образ системы со своими изменениями. А если обновлять ПО WD будет раз в день перекрывая какую-нибудь ошибку не с первого раза? Каждый день пересобирать? Не наш метод, опять-таки. Нам нужно сделать так, чтоб наше решение максимально стабильно жило без внешних воздействий. Значит смотрим в вывод mount ещё раз…
При изучении точек монтирования вполне себе можно заметить, что /usr/local/config монтируется с жёсткого диска, на котором, соответственно и лежит всё то, что может изменить пользователь из веб-морды устройства. В этой папке лежит пара десятков конфигов, сертификаты https, логи и прочий хлам. На данном этапе я не нашёл возможности изменить или добавить init скрипты, поэтому будем работать через cron. В него мы добавим свой скрипт, который будет запускать rsync (в моём случае. а вообще, конечно же, можно делать всё, что угодно). Итак. Нас интересует файл config.xml, лежащий там же. Это инструкции, что будет изменено в образе при загрузке. В моей версии фирмвари (2.21.119) он выглядит так:

root@xxx-d root # cat /usr/local/config/config.xml

<config>
 <sw_ver_1>2.21.119</sw_ver_1>
 <sw_ver_2>2.21.119.0901.2016</sw_ver_2>
 <hw_ver>WDMyCloud</hw_ver>
 <eula>1</eula>
 <language>9</language>
 <registered>0</registered>
 <eula_fw>0</eula_fw>
 <eula_apps>0</eula_apps>
 <analytics>0</analytics>
 <storage_scan>1</storage_scan>
 <network_mgr>
 <lan0>
 <speed>0</speed>
 <dhcp_enable>0</dhcp_enable>
 <ip>192.168.1.136</ip>
 <netmask>255.255.255.0</netmask>
 <gateway>192.168.1.254</gateway>
 <jumbo_enable>0</jumbo_enable>
 <jumbo_mtu>1500</jumbo_mtu>
 <vlan_enable>0</vlan_enable>
 <vlan_id>1</vlan_id>
 <dns_manual>1</dns_manual>
 <dns1>192.168.1.100</dns1>
 <dns2>192.168.1.254</dns2>
 <dns3></dns3>
 <dns1_bak>192.168.1.100</dns1_bak>
 <ipv6>
 <mode>off</mode>
 <local_ipv6address></local_ipv6address>
 <local_prefix_length></local_prefix_length>
 <dhcp_ipv6address></dhcp_ipv6address>
 <dhcp_prefix_length></dhcp_prefix_length>
 <gateway></gateway>
 <dns1></dns1>
 <dns2></dns2>
 <count>0</count>
 <item id="1">
 <ipv6address></ipv6address>
 <prefix_length></prefix_length>
 </item>
 <item id="2">
 <ipv6address></ipv6address>
 <prefix_length></prefix_length>
 </item>
 <dns_manual>0</dns_manual>
 </ipv6>
 <tunnel_broker>
 <enable>0</enable>
 <username></username>
 <password></password>
 <server>anonymous.freenet6.net</server>
 <ipv6address></ipv6address>
 </tunnel_broker>
 </lan0>
 <lan1>
 <speed>0</speed>
 <dhcp_enable>1</dhcp_enable>
 <ip>192.168.0.33</ip>
 <netmask>255.255.255.0</netmask>
 <gateway>192.168.0.1</gateway>
 <jumbo_enable>0</jumbo_enable>
 <jumbo_mtu>1500</jumbo_mtu>
 <vlan_enable>0</vlan_enable>
 <vlan_id>1</vlan_id>
 <dns_manual>0</dns_manual>
 <dns1></dns1>
 <dns2></dns2>
 <dns3></dns3>
 <ipv6>
 <mode>off</mode>
 <local_ipv6address></local_ipv6address>
 <local_prefix_length></local_prefix_length>
 <dhcp_ipv6address></dhcp_ipv6address>
 <dhcp_prefix_length></dhcp_prefix_length>
 <gateway></gateway>
 <dns1></dns1>
 <dns2></dns2>
 <count>0</count>
 <item id="1">
 <ipv6address></ipv6address>
 <prefix_length></prefix_length>
 </item>
 <item id="2">
 <ipv6address></ipv6address>
 <prefix_length></prefix_length>
 </item>
 <dns_manual>0</dns_manual>
 </ipv6>
 <tunnel_broker>
 <enable>0</enable>
 <username></username>
 <password></password>
 <server>anonymous.freenet6.net</server>
 <ipv6address></ipv6address>
 </tunnel_broker>
 </lan1>
 <bonding>
 <enable>0</enable>
 <mode>1</mode>
 </bonding>
 <default_gw>lan0</default_gw>
 <dhcp_server>
 <enable>0</enable>
 <s_ip>192.168.0.200</s_ip>
 <e_ip>192.168.0.254</e_ip>
 <lease>604800</lease>
 </dhcp_server>
 <ddns>
 <enable>0</enable>
 <username></username>
 <pwd></pwd>
 <domain></domain>
 <server></server>
 <timeout>2073600</timeout>
 <timestamp></timestamp>
 <ip></ip>
 </ddns>
 <lltd>
 <enable>0</enable>
 </lltd>
 <location>US</location>
 <company>WESTERN DIGITAL</company>
 <snmp>
 <enable>0</enable>
 <comm>public</comm>
 <trap>
 <enable>0</enable>
 <comm>public</comm>
 <server></server>
 </trap>
 </snmp>
 <upnp_test></upnp_test>
 <ssh>
 <enable>1</enable>
 </ssh>
 <web>
 <ssl_enable>0</ssl_enable>
 <ssl_port>443</ssl_port>
 <port>80</port>
 </web>
 </network_mgr>
 <system_mgr>
 <iscsi>
 <enable>0</enable>
 <iSNS>
 <enable>0</enable>
 <ip>0.0.0.0</ip>
 </iSNS>
 </iscsi>
 <quota>
 <enable>1</enable>
 </quota>
 <samba>
 <enable>1</enable>
 <workgroup>xxx.local</workgroup>
 <netbios_name>xxx-d</netbios_name>
 <server_string>xxxpromxxx</server_string>
 <lmb>0</lmb>
 <dfs_enable>0</dfs_enable>
 <ads_enable>0</ads_enable>
 <ads_workgroup></ads_workgroup>
 <ads_username></ads_username>
 <ads_password></ads_password>
 <ads_realm></ads_realm>
 <ads_pwd_server></ads_pwd_server>
 <smb2_enable>1</smb2_enable>
 </samba>
 <afp>
 <enable>1</enable>
 </afp>
 <iso_mount>
 <enable>1</enable>
 </iso_mount>
 <nfs>
 <enable>1</enable>
 </nfs>
 <webdav>
 <enable>0</enable>
 </webdav>
 <crond>
 <list>
 <count>6</count>
 <name id="1">stime</name>
 <name id="2">wd_crontab</name>
 <name id="3">app_get_info</name>
 <name id="4">recycle_bin_clear</name>
 <name id="5">chk_wfs_download</name>
 <name id="6">auto_fw</name>
 <name id="7">random_check</name>
 <name id="8">fw_available</name>
 <name id="9">user_expire_chk</name>
 </list>
 <stime>
 <count>1</count>
 <item id="1">
 <method>3</method>
 <1>30</1>
 <2>2</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>/usr/sbin/stime&amp;</run>
 </item>
 </stime>
 <wd_crontab>
 <count>1</count>
 <item id="1">
 <method>3</method>
 <1>0</1>
 <2>3</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>wd_crontab.sh&amp;</run>
 </item>
 </wd_crontab>
 <app_get_info>
 <count>1</count>
 <item id="1">
 <method>3</method>
 <1>0</1>
 <2>4</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>auto_fw -a -c&amp;</run>
 </item>
 </app_get_info>
 <recycle_bin_clear>
 <count>1</count>
 <item id="1">
 <method>3</method>
 <1>0</1>
 <2>0</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>auto_clear_recycle_bin.sh &amp;</run>
 </item>
 </recycle_bin_clear>
 <chk_wfs_download>
 <count>1</count>
 <item id="1">
 <method>3</method>
 <1>30</1>
 <2>3</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>/usr/sbin/chk_wfs_download&amp;</run>
 </item>
 </chk_wfs_download>
 <auto_fw>
 <item id="1">
 <method>3</method>
 <1>0</1>
 <2>3</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>auto_fw -d 1&amp;</run>
 </item>
 </auto_fw>
 <random_check>
 <item id="1">
 <method>3</method>
 <1>0</1>
 <2>0</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>random_check -s &amp;</run>
 </item>
 </random_check>
 <fw_available>
 <item id="1">
 <method>3</method>
 <1>3</1>
 <2>0</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>auto_fw -d 0 &amp;</run>
 </item>
 </fw_available>
 <user_expire_chk>
 <item id="1">
 <method>3</method>
 <1>0</1>
 <2>0</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>expire.sh</run>
 </item>
 </user_expire_chk>
 </crond>
 <time>
 <timezone>61</timezone>
 <ntp_enable>1</ntp_enable>
 <ntp_server></ntp_server>
 <ntp_server_bak></ntp_server_bak>
 <time_format>24</time_format>
 <date_format>YYYY-MM-DD</date_format>
 </time>
 <idle>
 <time>5</time>
 </idle>
 <power_management>
 <hdd_hibernation_enable>1</hdd_hibernation_enable>
 <turn_off_time>10</turn_off_time>
 <recovery_enable>1</recovery_enable>
 <fan>0</fan>
 <power_off_scheduling_enable>0</power_off_scheduling_enable>
 <led_enable>0</led_enable>
 <led_sleep>0</led_sleep>
 </power_management>
 <mail>
 <username></username>
 <pwd></pwd>
 <smtp></smtp>
 <sender></sender>
 <receiver></receiver>
 <port>25</port>
 <alert_type>0</alert_type>
 <alert_mail_priority>0</alert_mail_priority>
 <mail_event>
 <hdd_space_status_enable>0</hdd_space_status_enable>
 <hdd_space_status_interval>0</hdd_space_status_interval>
 <hdd_full_enable>0</hdd_full_enable>
 <hdd_full_define_full_percentage>95</hdd_full_define_full_percentage>
 <hdd_fail_enable>0</hdd_fail_enable>
 <hdd_degraded_enable>0</hdd_degraded_enable>
 <hdd_rebuild_is_done_enable>0</hdd_rebuild_is_done_enable>
 <hdd_temperature_enable>0</hdd_temperature_enable>
 <hdd_temperature_temperature>75</hdd_temperature_temperature>
 <hdd_temperature_kot>C</hdd_temperature_kot>
 <name_pwd_enable>0</name_pwd_enable>
 <firmware_update_enable>0</firmware_update_enable>
 <system_log_enable>0</system_log_enable>
 <bt_download_enable>0</bt_download_enable>
 <config_update_enable>0</config_update_enable>
 <smart_test_enable>0</smart_test_enable>
 <recover_power_fail_enable>0</recover_power_fail_enable>
 <hdd_start_rebuilding_enable>0</hdd_start_rebuilding_enable>
 <hdd_removed_enable>0</hdd_removed_enable>
 <hdd_inserted_enable>0</hdd_inserted_enable>
 <system_log_entry_full_enable>0</system_log_entry_full_enable>
 <ups_status_changed_enable>0</ups_status_changed_enable>
 </mail_event>
 <tls>0</tls>
 <auth_method>1</auth_method>
 <mail_1></mail_1>
 <mail_2></mail_2>
 <mail_3></mail_3>
 <mail_4></mail_4>
 <mail_5></mail_5>
 <enable>0</enable>
 </mail>
 <log>
 <enable>0</enable>
 <ip></ip>
 </log>
 <fw>
 <auto_update>1</auto_update>
 <sch_type>7</sch_type>
 <sch_hour>3</sch_hour>
 </fw>
 <lcd>0</lcd>
 <extended_log>
 <enable>0</enable>
 <path></path>
 </extended_log>
 <ups_management>
 <ups_pwr_recovery>0</ups_pwr_recovery>
 <ups_mode>0</ups_mode>
 <ups_plugmode>0</ups_plugmode>
 <ups_network>0</ups_network>
 </ups_management>
 </system_mgr>
 <app_mgr>
 <upnpavserver>
 <enable>0</enable>
 <analytics>0</analytics>
 </upnpavserver>
 <itunesserver>
 <enable>0</enable>
 </itunesserver>
 <ftp>
 <setting>
 <version>1.00</version>
 <maxclientsnumber>10</maxclientsnumber>
 <maxidletime>10</maxidletime>
 <port>21</port>
 <flowcontrol>0</flowcontrol>
 <filesystemcharset>UTF-8</filesystemcharset>
 <clientcharset>UTF-8</clientcharset>
 <passiveportrange>55536:55663</passiveportrange>
 <externalip></externalip>
 <state>1</state>
 <tlsencryption>1</tlsencryption>
 <forcepasvmode>0</forcepasvmode>
 <blockipstatus>1</blockipstatus>
 <anonymous_access>1</anonymous_access>
 <connectionperip>5</connectionperip>
 <monitorduration>5</monitorduration>
 <retryfails>5</retryfails>
 <fxpaccess>0</fxpaccess>
 <blockduration>5</blockduration>
 </setting>
 </ftp>
 </app_mgr>
 <backup_mgr>
 <rsyncd>
 <enable>0</enable>
 <rsyncd_pwd></rsyncd_pwd>
 <rsyncd_port>873</rsyncd_port>
 </rsyncd>
 <time_machine>
 <enable>0</enable>
 <merge_srv>1</merge_srv>
 </time_machine>
 </backup_mgr>
 <dsk_mgr>
 <hdd_config>
 <raid_auto_sync>0</raid_auto_sync>
 </hdd_config>
 <dsk_diagnostic></dsk_diagnostic>
 <volume_mapping>
 <volume_1>Volume_1</volume_1>
 <volume_2>Volume_2</volume_2>
 </volume_mapping>
 <smart>
 <test>
 <hd_a></hd_a>
 <hd_b></hd_b>
 <hd_c></hd_c>
 <hd_d></hd_d>
 </test>
 <hd_a_sn>WD-WCC4M1ZHE1FL</hd_a_sn>
 <hd_b_sn></hd_b_sn>
 <hd_c_sn></hd_c_sn>
 <hd_d_sn></hd_d_sn>
 </smart>
 </dsk_mgr>
 <account_mgr>
 <users></users>
 </account_mgr>
 <wizard_mgr></wizard_mgr>
 <status_mgr></status_mgr>
 <raccess_mgr></raccess_mgr>
 <download_mgr>
 <p2p>
 <enable>0</enable>
 </p2p>
 <usb_backup>
 <enable>0</enable>
 <direction>0</direction>
 <sour></sour>
 <dest></dest>
 <type>0</type>
 </usb_backup>
 <mtp_backup>
 <enable>0</enable>
 <dst></dst>
 <automatic>0</automatic>
 <mode>0</mode>
 <transfer_folder>/Public/USB Import</transfer_folder>
 <folder_option>0</folder_option>
 <folder_name></folder_name>
 </mtp_backup>
 </download_mgr>
 <media></media>
 <cloud>
 <enable>0</enable>
 </cloud>
 <recycle_bin>
 <auto_clear>0</auto_clear>
 <day>30</day>
 </recycle_bin>
</config>

Файл сам по себе довольно интересен и в нём видны настройки возможностей, которых в веб морде ни разу нет (например — dhcp сервер или iSCSI) и с ним надо будет поиграться попозже, но сейчас нас интересует секция про crond (начиная со строки 181 в моём листинге). Это то, что при загрузке будет засунуто в crontab пользователя root. Сюда мы и добавим наш скриптик. Добавляем строку

<name id="10">my_wd_start</name>

UPD: В последнем обновлении id с номером 10 занят, WD добавляет фичи. Соответственно, для какой-то гарантии меняем строку на

<name id="20">my_wd_start</name>

До 20 они, думаю, не скоро доберутся 🙂

и секцию

			
 <my_wd_start>
 <item id="1">
 <method>3</method>
 <1>*/5</1>
 <2>*</2>
 <3>*</3>
 <4>*</4>
 <5>*</5>
 <run>/usr/local/config/custom_run.sh</run>
 </item>
 </my_wd_start>

Сначала я попытался добавить в cron инструкцию @reboot, но wd отказался её выполнять. Соответственно пришлось добавлять скрипт, выполняемый раз в 5 минут и обезопашивать себя от многократного его выполнения (для тех, кто мало работает со скриптами на bash/sh — пробелы очень даже значимы):

root@xxx-d root # cat /usr/local/config/custom_run.sh
#!/bin/bash

CHK_FILE="/var/run/custom.run"
VRUN=date
if [ ! -f $CHK_FILE ]; then
/usr/sbin/rsync --daemon --config=/usr/local/config/rsyncd.conf
touch $CHK_FILE
echo $USER $VRUN > $CHK_FILE
fi
root@xxx-d root #

Конфиги rsync, естественно, кладём в ту же /usr/local/config и говорим ему, где их брать. В итоге имеем автостартующий (максимум через 5 минут после загрузки) rsync-демон. И потенциально — всё, что угодно. И всё это будет работать после обновления ПО и до тех пор, пока WD не уберёт rsync из прошивки)))

Помогла заметка - поделись с другом:
    • zingarini
    • 28 ноября, 2020

    Автор сделал то, о чем даже в комьюнити WD не в курсе, а тема поднималась и не раз. Точнее решение все же нашли, но не столь красивое.
    Насколько я понимаю, сам crontab сам перезаписывает задачи для cron раз в сутки, поэтому важно после правки config.xml перезагрузиться, тогда изменения сохраняются перманентно.
    Огромное спасибо за пост!

    • neo
    • 10 января, 2017

    Юрьевич, а как теперь у тебя отписаться? Есть интересная тема, будем точнее — комплекс, а именно TeamSpeak Server + онлайн список клиентов + пара еще интересных моментов, но как все это добро выложить не нашОл

    • давай действующую мыльницу — подниму учётку, а то тут ещё @terrenum.ru
      сюда или в a{зобакен}2801.ru

        • neo
        • 13 января, 2017

        охохонюшки какой домен вспомнилсо
        njinstead@yandex.ru
        дествует, пасип заранее, а то мне сложить для памяти некуда, так и не завел подобный домен, а пакетик получился неслабый, надо запомнить как ) мало ли…

        • парол туда улетэл, вроде как. есличто — восстанавливай на этот ящег, я его в учётку подоткнуль.

  1. 25 ноября, 2021

Оставьте эти два поля как есть:

 
Яндекс.Метрика
Array ( [path] => /var/sites/homeless.su/www/wp-content/uploads/2023/12 [url] => https://www.homeless.su/wp-content/uploads/2023/12 [subdir] => /2023/12 [basedir] => /var/sites/homeless.su/www/wp-content/uploads [baseurl] => https://www.homeless.su/wp-content/uploads [error] => )