如何观看对SQlite数据库的更改和触发器Shell脚本

时间:2019-02-28 00:40:01

标签: sql linux shell sqlite firefox

注意:我相信我可能缺少此问题的简单解决方案。我是编程新手。任何建议表示赞赏。

问题:一小群人(约3-5个)希望能够自动将下载的文件归档在适当的文件夹中。文件将被下载到共享下载文件夹中。该下载文件夹中的文件将根据它们的文件类型,下载文件的URL等被分类为一个大型共享文件夹结构。这些文件存储在共享服务器上,实际排序将通过服务器上运行的某种Shell脚本完成。

尽管有一些实用程序可以执行此操作(例如Maid),但它们并不能完成我希望它们执行的所有操作。例如,女佣没有办法在Linux中获取文件的下载URL。此外,它是用Ruby编写的,我想避免。

然后最大的绊脚石就是找到一种方法来获取可以传递到Shell脚本中的下载文件的url。最初,我认为可以通过 getfattr 完成此操作,该操作将获取文件的扩展属性。令人沮丧的是,尽管Chrome将文件的下载网址保存为扩展属性,但Firefox似乎并没有做同样的事情。因此,依靠扩展属性似乎是不可能的。

但是Firefox所做的是将下载的“元数据”存储在 places.sqlite 文件的两个单独的表中- moz_annos moz_places 。受此启发,我致力于构建一个Firefox扩展,在完成下载后,将有关下载文件的所有信息写入我们服务器上的SQLite数据库 downloads.sqlite 中。其中包括下载文件的url,MIME类型等。

这个想法是,利用这些数据,服务器可以运行一个shell脚本,对下载的文件进行细粒度的排序,使其进入我们的共享文件系统。

但是,我正在努力寻找一种稳定,可靠且可移植的方式来“触发”将实际移动文件的脚本,并将有关这些文件的信息传递给脚本,以便它可以对它们进行相应的排序。

我认为有几种方法可以解决此问题。我不确定哪种方法最合适:

1)观看下载文件夹

此方法将监视共享下载目录的更改,然后使用已下载文件的文件名查询 downloads.sqlite ,获取匹配的行,然后将文件的属性最终传递到排序所述文件的bash脚本。

困难:寻找一种方法来可靠地将下载的文件与数据库中的相应记录进行匹配。文件可能具有相同的下载名称,但是可能需要进行不同的排序,例如,如果文件是从其他URL下载的,则可能不同。另外,我想获得其他属性,例如whether the file was downloaded in incognito mode

2)创建辅助“帮助器”文件

在文件下载事件中,扩展名会创建一个“帮助程序”文本文件,该文件是文件名+一些包含附加文件属性的标记:

/Downloads/
mydownload.pdf
mydownload-downloadhelper.txt

然后服务器可以在downloads目录中监视.txt文件的创建,并从中运行必要的shell脚本。

困难:虽然这避免了使用SQlite数据库,但看起来似乎很不友好,也很笨拙,我可以看到很多方法都无法使用或失效。

3)观看 SQlite数据库

此方法将写入服务器上的共享SQlite数据库 downloads.sqlite 。然后,通过某种方法,在该数据库中寻找新的一行插入。这可能是通过在表上查看新的INSERT的sqlite数据库中进行,或者是在运行bash脚本的INSERT上具有sqlite触发器,然后将下载信息传递到Shell脚本中。

困难:似乎没有任何简单的方法来查看SQlite数据库中是否有新行插入,并且SQlite中的触发器似乎无法启动外部脚本/程序。我一直在寻找可以同时执行这两个过程的方法,但我一直在努力寻找能够理解的任何记录方法。

我想要的是:

  • 一些反馈有关哪种方法合适,或者是否有我忽略的更合适的方法。
  • 一个与此类似的系统/程序示例。

非常感谢。

1 个答案:

答案 0 :(得分:0)

在我看来,您已经把“马车放在马的前面”:

使用cron定期检查是否有新下载。在命令行上处理它们,而不是尝试从sqlite3内部触发事件:

a)这是使用共享的sqlite3数据库“ downloads.sqlite”的方法:

预先支付一次:

  1. 向您的数据库添加一个表,该表仅包含一个整数作为记录计数器和一个timeStamp字段,例如“ table_counter”:

     sqlite3 downloads.sqlite "CREATE TABLE "table_counter" ( "counter" INTEGER PRIMARY KEY  NOT NULL, "timestamp" DATETIME DEFAULT (datetime('now','UTC')));" 2>/dev/null
    
  2. 将初始记录插入此新表中,将“计数器”设置为零并记录timeStamp:

     sqlite3 downloads.sqlite "INSERT INTO "table_counter" VALUES (0, (SELECT datetime('now','UTC')));" 2>/dev/null
    


很多时候:

  1. 使用“ SELECT COUNT(*)”语句查询包含下载内容的表:

     sqlite3 downloads.sqlite "SELECT COUNT(*) from table_downloads;" 2>/dev/null
    

结果,例如20

  1. 将此数字与记录计数器字段中存储的数字进行比较:

    sqlite3 downloads.sqlite "SELECT (counter) from table_counter;" 2>/dev/null
    

结果,例如17

  1. 如果来自3)的结果>来自4)的结果,则说明您下载的文件多于已处理的文件。 如果是这样,请使用“ subselect”,使用“ SELECT”语句查询包含下载内容的表中最旧的尚未处理的下载内容:

     sqlite3 downloads.sqlite "SELECT * from table_downloads where rowid = (SELECT (counter+1) from table_counter);" 2>/dev/null
    

在我的示例中,这将为rowid为17 + 1 = 18的数据记录选择所有值;

  1. 对存储为记录#18的下载文件大加赞赏。

  2. 再次使用子选择来增加“ table_counter”中的记录计数器:

     sqlite3 downloads.sqlite "UPDATE table_counter SET counter = (SELECT (counter) from table_counter)+1;" 2>/dev/null
    
  3. 最后,更新“ table_counter”的时间戳: 为什么?狗屎在共享驱动器上发生...通过这种方式,您可以始终检查已处理了多少个下载记录以及上次何时发生。

     sqlite3 downloads.sqlite "UPDATE table_counter SET timeStamp = datetime('now','UTC');" 2>/dev/null
    
  4. 如果要获取此处理的日志,则将4)中的SQL语句更改为“ SELECT COUNT(*)”,将7)中的SQL语句更改为“ INSERT counter”,并将其子选择更改为“(分别从table_counter中选择(counter + 1))...

请注意:SQL语句末尾的重定向“ 2> / dev / null”只是为了在显示查询结果之前取消由较新版本的SQLite3发出的此类行。

    -- Loading resources from /usr/home/bernie/.sqliterc

如果您不喜欢基于UTC的时间戳,请改用localtime

    (datetime('now','localtime'))

在shell脚本中放置步骤3)(包括8),并使用cron条目定期运行此查询/比较...

在此shell脚本中使用完整的/path/to/sqlite3(以防万一在共享驱动器上运行。有人可能在鬼混路径,可能会使您的cron感到惊讶)

b)我将在单独的答案中使用awk和一些像md5这样的哈希为您提供一个更简单的答案。

因此,对将来的读者来说更容易,对您“评级”也更容易:-)