apt жалуется на изменение версии Suite с тестовой на стабильную

Я обнаружил этот вопрос, когда писал свой сценарий примерно для той же цели, и ваша идея о кэшировании файлов с их dev+inode+size+mtime показалась мне очень полезной, поэтому я добавил ее. Ваша идея и моя реализация отличаются, так как я поздно наткнулся на эту страницу и решил не переписывать все:

  1. Сценарий для простоты хранит записи кэша в одном файле YAML. Вы по-прежнему можете поделиться этим файлом на нескольких машинах, но есть риск RCE, плюс вам нужно будет написать блокирующую оболочку из-за TOCTOU в файле YAML.

  2. Вероятно, это будет работать только в Linux и, если повезет, в других Unix-системах.

  3. Используйте на свой страх и риск. Содержимое вашего кэша не будет защищено.

Сначала запустите gem install chronic_duration.

#!/usr/bin/env ruby
# Usage: memoize [-D DATABASE] [-T TIMEOUT] [-F] [--] COMMAND [ARG]...
#     or memoize [-D DATABASE] --cleanup
#
# OPTIONS
#   -D DATABASE      Store entries in YAML format in DATABASE file.
#   -T TIMEOUT       Invalidate memoized entries older than TIMEOUT.
#   -F               Track file changes (dev+inode+size+mtime).
#   --cleanup        Remove all stale entries.

require 'date'
require 'optparse'
require 'digest'
require 'yaml'
require 'chronic_duration'
require 'open3'

MYSELF          = File.basename(__FILE__)
DEFAULT_DBFILE  = "#{Dir.home}/.config/memoize.yml"
DEFAULT_TIMEOUT = '1 week'

def fc(fpath) # File characteristic
  return [:dev, :ino, :size, :mtime].map do |s|
    Digest::SHA1.digest(Integer(File.stat(fpath).send(s)).to_s.b)
  end.join
end

def cmdline_checksum(cmdline, fchanges)
  pre_cksum_bytes = "".b

  cmdline.each do |c|
    characteristic   = (File.exists?(c) and fchanges) ? fc(c) : c
    pre_cksum_bytes += Digest::SHA1.digest(characteristic)
  end

  return Digest::SHA1.digest(pre_cksum_bytes)
end

def timed_out?(entry)
  return (entry[:timestamp] + Integer(entry[:timeout])) < Time.now
end

def pluralize(n, singular, plural)
  return (n % 100 == 11 || n % 10 != 1) ? plural : singular
end

fail "memoize: FATAL: this is a script, not a library" unless __FILE__ == $0

$dbfile   = DEFAULT_DBFILE
$timeout  = DEFAULT_TIMEOUT
$fchanges = false
$cleanup  = false
$retcode  = 0
$replay   = false

ARGV.options do |o|
  o.version = '2018.06.23'
  o.banner  = "Usage: memoize [OPTION]... [--] COMMAND [ARG]...\n"+
              "Cache results of COMMAND and replay its output"

  o.separator ""
  o.separator "OPTIONS"

  o.summary_indent = "  "
  o.summary_width  = 17

  o.on('-D=DATABASE', "Default: #{DEFAULT_DBFILE}")       { |d| $dbfile   = d    }
  o.on('-T=TIMEOUT',  "Default: #{DEFAULT_TIMEOUT}")      { |t| $timeout  = t    }
  o.on('-F', "Track file changes (dev+inode+size+mtime)") {     $fchanges = true }
  o.on('--cleanup', "Remove all stale entries")           {     $cleanup  = true }
end.parse!

begin
  File.open($dbfile, 'a') {}
  File.chmod(0600, $dbfile)
end unless File.exists?($dbfile)

db      = (YAML.load(File.read($dbfile)) or {})
cmdline = ARGV
cksum   = cmdline_checksum(cmdline, $fchanges)
entry   = {
  cmdline:   cmdline,
  timestamp: Time.now,
  timeout:   '1 week',
  stdout:    "",
  stderr:    "",
  retcode:   0,
}

if $cleanup
  entries = db.keys.select{|k| timed_out?(db[k]) }
  c = entries.count

  entries.each do |k|
    db.delete(k)
  end

  STDERR.puts "memoize: NOTE: #{c} stale #{pluralize(c, "entry", "entries")} removed"

  File.open($dbfile, 'w') { |f| f << YAML.dump(db) }

  exit
end

$replay = db.key?(cksum) && (not timed_out?(db[cksum]))

if $replay
  entry = db[cksum]
else
  Open3.popen3(*cmdline) do |i, o, e, t|
    i.close
    entry[:stdout]    = o.read
    entry[:stderr]    = e.read
    entry[:retcode]   = t.value.exitstatus
  end

  entry[:timestamp] = Time.now
  entry[:timeout]   = Integer(ChronicDuration.parse($timeout))
  db[cksum] = entry
end

$retcode = entry[:retcode]
STDOUT.write(entry[:stdout]) # NOTE: we don't record or replay stream timing
STDERR.write(entry[:stderr])
STDOUT.flush
STDERR.flush

File.open($dbfile, 'w') { |f| f << YAML.dump(db) }

exit! $retcode
3
12.06.2020, 20:36
0 ответов

Теги

Похожие вопросы