読者です 読者をやめる 読者になる 読者になる

歩いたら休め

If the implementation is easy to explain, it may be a good idea.

【R】ファイルサーバー上のファイルの更新を定期的に確認するスクリプトを作成中

弊社には古より伝わったファイルサーバー上のExcelPowerPointで色々な仕様書や必要な情報がやりとりされる文化があります。 (正直不便すぎるのでやめてほしいのですが、すぐに変更できるとは思えないし、過去の遺産もあるのでなんとか作業しなければいけません。)

そんな中、「ファイルサーバーのファイルを監視して更新されたら通知してくれる仕組みが欲しい」と言っている同期がおり、 確かに便利そうなのでなんとか実現しようとしています。 ローカルのWindowsPC以外で、ファイルサーバーに接続する方法が分からないので、 とりあえずローカルマシンで動いてセットアップが簡単な言語…ということでRで実装し始めてみました。

まず、Rでファイルの更新を確認するスクリプトを書き、 それをwindowsのタスクスケジューラーで30分おきくらいに実行すればいいかなと考えました。

www.atmarkit.co.jp

とりあえず下記のようなcsvで設定ファイル(監視したいファイルパスと更新日時を記録したもの)を作り、 それをクロールして更新されていたら通知します。 (csvならwindowsお得意のExcelで開けますもんね。)

target_file,last_modified
//xxx/yyy/DB仕様書.xlsx,2015-05-16 08:43:32 JST
//xxx/yyy/データベース.xlsx,2015-12-16 12:10:01 JST

R自体のコードはこんな感じです。

library(dplyr)
library(purrr)
 
confpath <- './config.csv'

# 設定ファイルを読み込む
read_config <- function(confpath) {
  return(
    read.csv(confpath, stringsAsFactors=FALSE)
  )
}
 
# ファイルの更新日時を取得する
get_last_modified <- function(filepath) {
  return(
    file.info(filepath)$mtime
  )
}
 
# 更新されたファイルのリストを作成
get_updated_files <- function(config) {
  return(
    config %>%
      dplyr::mutate(new_last_modified = get_last_modified(target_file)) %>%
      dplyr::filter(last_modified != new_last_modified) %>% 
      dplyr::select(target_file) %>%
      unlist(use.names = FALSE)
  )
}
 
# アラート文を作成する
make_alert_message <- function(filepaths) {
  return(
    paste(
      '以下のファイルが更新されています',
      filepaths %>% purrr::reduce(paste, sep='\n'), # 最近流行りのpurrrですよ!
      sep='\n'
    )
  )
}
 
# messageの内容をメールアラートか何かで飛ばす関数
send_mail_alert <- function(message) {
  # 未実装、この辺のライブラリを参考にする
  # http://www.slideshare.net/TokorosawaYoshio/r41-36956682
}

# configの設定ファイルを更新する
update_config <- function(config, confpath) {
  config %>%
    dplyr::mutate(new_last_modified = get_last_modified(target_file)) %>%
    dplyr::select(target_file, last_modified = new_last_modified) %>%
    write.csv(confpath, quote=FALSE, row.names=FALSE)
}
 
# Pythonの if __name__ == "__main__": みたいなものはこう書くらしい
if(interactive()) {
  config <- read_config(confpath)
 
  # メールアラートを飛ばす
  config %>%
    get_updated_files() %>%
    make_alert_message() %>%
    send_mail_alert()
 
  # configを更新する
  update_config(config, confpath)
}

ただ、R言語も社内では利用者が多いとはいえないため、できればPythonのpy2exe等のように、 exe形式でコンパイルしたほうがほかの人にとって使い勝手いいかなと思います。 (しかし、下の投稿を見る限り難しい?)

stackoverflow.com

優秀な先輩が他人の作業を自動化するRのコードを書いたのですが、 相手がプログラマーじゃなくて実行環境が無いとかでその後のメンテナンスやエラー時の対応をさせられてしまっている姿を見ていたので、 同じ轍を踏まないように気をつけなければいけません。 また、多少は誰かに褒められたいということもあります。

というわけで、Pythonで書きなおしてexeファイルにコンパイルしようかなと思ってます。