etch 3.13 → 3.15.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/etchclient.rb +127 -108
- metadata +3 -6
- data/etc/ca.pem +0 -1
- data/etc/dhparams +0 -9
- data/man/man8/etch.8 +0 -204
data/Rakefile
CHANGED
@@ -3,7 +3,7 @@ spec = Gem::Specification.new do |s|
|
|
3
3
|
s.name = 'etch'
|
4
4
|
s.summary = 'Etch system configuration management client'
|
5
5
|
s.add_dependency('facter')
|
6
|
-
s.version = '3.
|
6
|
+
s.version = '3.15.0'
|
7
7
|
s.author = 'Jason Heiss'
|
8
8
|
s.email = 'etch-users@lists.sourceforge.net'
|
9
9
|
s.homepage = 'http://etch.sourceforge.net'
|
data/lib/etchclient.rb
CHANGED
@@ -35,13 +35,13 @@ require 'logger'
|
|
35
35
|
require 'etch'
|
36
36
|
|
37
37
|
class Etch::Client
|
38
|
-
VERSION = '3.
|
38
|
+
VERSION = '3.15.0'
|
39
39
|
|
40
40
|
CONFIRM_PROCEED = 1
|
41
41
|
CONFIRM_SKIP = 2
|
42
42
|
CONFIRM_QUIT = 3
|
43
43
|
PRIVATE_KEY_PATHS = ["/etc/ssh/ssh_host_rsa_key", "/etc/ssh_host_rsa_key"]
|
44
|
-
CONFIGDIR = '/etc
|
44
|
+
CONFIGDIR = '/etc'
|
45
45
|
|
46
46
|
# We need these in relation to the output capturing
|
47
47
|
ORIG_STDOUT = STDOUT.dup
|
@@ -141,17 +141,17 @@ class Etch::Client
|
|
141
141
|
http = Net::HTTP.new(@filesuri.host, @filesuri.port)
|
142
142
|
if @filesuri.scheme == "https"
|
143
143
|
# Eliminate the OpenSSL "using default DH parameters" warning
|
144
|
-
if File.exist?(File.join(CONFIGDIR, 'dhparams'))
|
145
|
-
dh = OpenSSL::PKey::DH.new(IO.read(File.join(CONFIGDIR, 'dhparams')))
|
144
|
+
if File.exist?(File.join(CONFIGDIR, 'etch', 'dhparams'))
|
145
|
+
dh = OpenSSL::PKey::DH.new(IO.read(File.join(CONFIGDIR, 'etch', 'dhparams')))
|
146
146
|
Net::HTTP.ssl_context_accessor(:tmp_dh_callback)
|
147
147
|
http.tmp_dh_callback = proc { dh }
|
148
148
|
end
|
149
149
|
http.use_ssl = true
|
150
|
-
if File.exist?(File.join(CONFIGDIR, 'ca.pem'))
|
151
|
-
http.ca_file = File.join(CONFIGDIR, 'ca.pem')
|
150
|
+
if File.exist?(File.join(CONFIGDIR, 'etch', 'ca.pem'))
|
151
|
+
http.ca_file = File.join(CONFIGDIR, 'etch', 'ca.pem')
|
152
152
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
153
|
-
elsif File.directory?(File.join(CONFIGDIR, 'ca'))
|
154
|
-
http.ca_path = File.join(CONFIGDIR, 'ca')
|
153
|
+
elsif File.directory?(File.join(CONFIGDIR, 'etch', 'ca'))
|
154
|
+
http.ca_path = File.join(CONFIGDIR, 'etch', 'ca')
|
155
155
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
156
156
|
end
|
157
157
|
end
|
@@ -403,7 +403,9 @@ class Etch::Client
|
|
403
403
|
rescue Exception => e
|
404
404
|
status = 1
|
405
405
|
$stderr.puts e.message
|
406
|
+
message << e.message
|
406
407
|
$stderr.puts e.backtrace.join("\n") if @debug
|
408
|
+
message << e.backtrace.join("\n") if @debug
|
407
409
|
end # begin/rescue
|
408
410
|
end # catch
|
409
411
|
|
@@ -540,8 +542,10 @@ class Etch::Client
|
|
540
542
|
# original file.
|
541
543
|
if config.elements['/config/revert']
|
542
544
|
origpathbase = File.join(@origbase, file)
|
545
|
+
origpath = nil
|
543
546
|
|
544
547
|
# Restore the original file if it is around
|
548
|
+
revert_occurred = false
|
545
549
|
if File.exist?("#{origpathbase}.ORIG")
|
546
550
|
origpath = "#{origpathbase}.ORIG"
|
547
551
|
origdir = File.dirname(origpath)
|
@@ -553,10 +557,7 @@ class Etch::Client
|
|
553
557
|
|
554
558
|
puts "Restoring #{origpath} to #{file}"
|
555
559
|
recursive_copy_and_rename(origdir, origbase, file) if (!@dryrun)
|
556
|
-
|
557
|
-
# Now remove the backed-up original so that future runs
|
558
|
-
# don't do anything
|
559
|
-
remove_file(origpath) if (!@dryrun)
|
560
|
+
revert_occurred = true
|
560
561
|
elsif File.exist?("#{origpathbase}.TAR")
|
561
562
|
origpath = "#{origpathbase}.TAR"
|
562
563
|
filedir = File.dirname(file)
|
@@ -566,19 +567,24 @@ class Etch::Client
|
|
566
567
|
|
567
568
|
puts "Restoring #{file} from #{origpath}"
|
568
569
|
system("cd #{filedir} && tar xf #{origpath}") if (!@dryrun)
|
569
|
-
|
570
|
-
# Now remove the backed-up original so that future runs
|
571
|
-
# don't do anything
|
572
|
-
remove_file(origpath) if (!@dryrun)
|
570
|
+
revert_occurred = true
|
573
571
|
elsif File.exist?("#{origpathbase}.NOORIG")
|
574
572
|
origpath = "#{origpathbase}.NOORIG"
|
575
573
|
puts "Original #{file} didn't exist, restoring that state"
|
576
574
|
|
577
575
|
# Remove anything we might have written out for this file
|
578
576
|
remove_file(file) if (!@dryrun)
|
577
|
+
revert_occurred = true
|
578
|
+
end
|
579
|
+
|
580
|
+
# Update the history log
|
581
|
+
if revert_occurred
|
582
|
+
save_history(file)
|
583
|
+
end
|
579
584
|
|
580
|
-
|
581
|
-
|
585
|
+
# Now remove the backed-up original so that future runs
|
586
|
+
# don't do anything
|
587
|
+
if origpath
|
582
588
|
remove_file(origpath) if (!@dryrun)
|
583
589
|
end
|
584
590
|
|
@@ -1696,109 +1702,112 @@ class Etch::Client
|
|
1696
1702
|
|
1697
1703
|
origpath
|
1698
1704
|
end
|
1699
|
-
|
1705
|
+
|
1700
1706
|
# This subroutine maintains a revision history for the file in @historybase
|
1701
1707
|
def save_history(file)
|
1702
|
-
|
1708
|
+
histdir = File.join(@historybase, "#{file}.HISTORY")
|
1709
|
+
current = File.join(histdir, 'current')
|
1710
|
+
|
1711
|
+
# Migrate old RCS history
|
1712
|
+
if File.file?(histdir) && File.directory?(File.join(File.dirname(histdir), 'RCS'))
|
1713
|
+
if !@dryrun
|
1714
|
+
puts "Migrating old RCS history to new format"
|
1715
|
+
rcsmax = nil
|
1716
|
+
IO.popen("rlog #{histdir}") do |pipe|
|
1717
|
+
pipe.each do |line|
|
1718
|
+
if line =~ /^head: 1.(.*)/
|
1719
|
+
rcsmax = $1.to_i
|
1720
|
+
break
|
1721
|
+
end
|
1722
|
+
end
|
1723
|
+
end
|
1724
|
+
if !rcsmax
|
1725
|
+
raise "Failed to parse RCS history rlog output"
|
1726
|
+
end
|
1727
|
+
tmphistdir = tempdir(histdir)
|
1728
|
+
1.upto(rcsmax) do |rcsrev|
|
1729
|
+
rcsrevcontents = `co -q -p1.#{rcsrev} #{histdir}`
|
1730
|
+
# rcsrev-1 because RCS starts revisions at 1.1 and we start files
|
1731
|
+
# at 0000
|
1732
|
+
File.open(File.join(tmphistdir, sprintf('%04d', rcsrev-1)), 'w') do |rcsrevfile|
|
1733
|
+
rcsrevfile.write(rcsrevcontents)
|
1734
|
+
end
|
1735
|
+
end
|
1736
|
+
FileUtils.copy(histdir, File.join(tmphistdir, 'current'))
|
1737
|
+
File.delete(histdir)
|
1738
|
+
File.rename(tmphistdir, histdir)
|
1739
|
+
end
|
1740
|
+
end
|
1703
1741
|
|
1704
1742
|
# Make sure the directory tree for this file exists in the
|
1705
1743
|
# directory we save history in.
|
1706
|
-
|
1707
|
-
|
1708
|
-
puts "Making directory tree #{histdir}"
|
1744
|
+
if !File.exist?(histdir)
|
1745
|
+
puts "Making history directory #{histdir}"
|
1709
1746
|
FileUtils.mkpath(histdir) if (!@dryrun)
|
1710
1747
|
end
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
#
|
1719
|
-
|
1720
|
-
# previously but the history log was not started at the same time.
|
1721
|
-
# There are a variety of reasons why this might be the case (the
|
1722
|
-
# original was saved by a previous version of etch that didn't have
|
1723
|
-
# the history log feature, or the original was saved manually by
|
1724
|
-
# someone) but whatever the reason is we want to use the original
|
1725
|
-
# backup to start the history log before updating the history log
|
1726
|
-
# with the current file.
|
1727
|
-
if !File.exist?(histpath) && !@first_update[file]
|
1748
|
+
|
1749
|
+
# If the history log doesn't exist and we didn't just create the original
|
1750
|
+
# backup then that indicates that the original backup was made previously
|
1751
|
+
# but the history log was not started at the same time. There are a
|
1752
|
+
# variety of reasons why this might be the case (the most likely is that
|
1753
|
+
# the original was saved manually by someone) but whatever the reason is
|
1754
|
+
# we want to use the original backup to start the history log before
|
1755
|
+
# updating the history log with the current file.
|
1756
|
+
if !File.exist?(File.join(histdir, 'current')) && !@first_update[file]
|
1728
1757
|
origpath = save_orig(file)
|
1729
1758
|
if File.file?(origpath) && !File.symlink?(origpath)
|
1730
1759
|
puts "Starting history log with saved original file: " +
|
1731
|
-
|
1732
|
-
FileUtils.copy(origpath,
|
1760
|
+
"#{origpath} -> #{current}"
|
1761
|
+
FileUtils.copy(origpath, current) if (!@dryrun)
|
1733
1762
|
else
|
1734
1763
|
puts "Starting history log with 'ls -ld' output for " +
|
1735
|
-
|
1736
|
-
system("ls -ld #{origpath} > #{
|
1737
|
-
end
|
1738
|
-
# Check the newly created history file into RCS
|
1739
|
-
histbase = File.basename(histpath)
|
1740
|
-
puts "Checking initial history log into RCS: #{histpath}"
|
1741
|
-
if !@dryrun
|
1742
|
-
# The -m flag shouldn't be needed, but it won't hurt
|
1743
|
-
# anything and if something is out of sync and an RCS file
|
1744
|
-
# already exists it will prevent ci from going interactive.
|
1745
|
-
system(
|
1746
|
-
"cd #{histdir} && " +
|
1747
|
-
"ci -q -t-'Original of an etch modified file' " +
|
1748
|
-
"-m'Update of an etch modified file' #{histbase} && " +
|
1749
|
-
"co -q -r -kb #{histbase}")
|
1764
|
+
"saved original file: #{origpath} -> #{current}"
|
1765
|
+
system("ls -ld #{origpath} > #{current} 2>&1") if (!@dryrun)
|
1750
1766
|
end
|
1751
1767
|
set_history_permissions(file)
|
1752
1768
|
end
|
1753
|
-
|
1754
|
-
#
|
1755
|
-
|
1756
|
-
# If the file already exists in RCS we need to check out a locked
|
1757
|
-
# copy before updating it
|
1758
|
-
histbase = File.basename(histpath)
|
1759
|
-
rcsstatus = false
|
1760
|
-
if !@dryrun
|
1761
|
-
rcsstatus = system("cd #{histdir} && rlog -R #{histbase} > /dev/null 2>&1")
|
1762
|
-
end
|
1763
|
-
if rcsstatus
|
1764
|
-
# set_history_permissions may set the checked-out file
|
1765
|
-
# writeable, which normally causes co to abort. Thus the -f
|
1766
|
-
# flag.
|
1767
|
-
system("cd #{histdir} && co -q -l -f #{histbase}") if !@dryrun
|
1768
|
-
end
|
1769
|
-
|
1769
|
+
|
1770
|
+
# Make temporary copy of file
|
1771
|
+
newcurrent = current+'.new'
|
1770
1772
|
if File.file?(file) && !File.symlink?(file)
|
1771
|
-
puts "Updating history log: #{file} -> #{
|
1772
|
-
|
1773
|
+
puts "Updating history log: #{file} -> #{current}"
|
1774
|
+
if File.exist?(newcurrent)
|
1775
|
+
remove_file(newcurrent)
|
1776
|
+
end
|
1777
|
+
FileUtils.copy(file, newcurrent) if (!@dryrun)
|
1773
1778
|
else
|
1774
|
-
puts "Updating history log with 'ls -ld' output: "
|
1775
|
-
|
1776
|
-
system("ls -ld #{file} > #{histpath} 2>&1") if (!@dryrun)
|
1779
|
+
puts "Updating history log with 'ls -ld' output: #{file} -> #{current}"
|
1780
|
+
system("ls -ld #{file} > #{newcurrent} 2>&1") if (!@dryrun)
|
1777
1781
|
end
|
1778
|
-
|
1779
|
-
#
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1782
|
+
|
1783
|
+
# Roll current to next XXXX if current != XXXX
|
1784
|
+
if File.exist?(current)
|
1785
|
+
nextfile = '0000'
|
1786
|
+
maxfile = Dir.entries(histdir).select{|e|e=~/^\d+/}.max
|
1787
|
+
if maxfile
|
1788
|
+
if compare_file_contents(File.join(histdir, maxfile), File.read(current))
|
1789
|
+
nextfile = nil
|
1790
|
+
else
|
1791
|
+
nextfile = sprintf('%04d', maxfile.to_i + 1)
|
1792
|
+
end
|
1793
|
+
end
|
1794
|
+
if nextfile
|
1795
|
+
File.rename(current, File.join(histdir, nextfile)) if (!@dryrun)
|
1796
|
+
end
|
1791
1797
|
end
|
1792
|
-
|
1798
|
+
|
1799
|
+
# Move temporary copy to current
|
1800
|
+
File.rename(current+'.new', current) if (!@dryrun)
|
1801
|
+
|
1793
1802
|
set_history_permissions(file)
|
1794
1803
|
end
|
1795
|
-
|
1804
|
+
|
1796
1805
|
# Ensures that the history log file has appropriate permissions to avoid
|
1797
1806
|
# leaking information.
|
1798
1807
|
def set_history_permissions(file)
|
1799
1808
|
origpath = File.join(@origbase, "#{file}.ORIG")
|
1800
|
-
|
1801
|
-
|
1809
|
+
histdir = File.join(@historybase, "#{file}.HISTORY")
|
1810
|
+
|
1802
1811
|
# We set the permissions to the more restrictive of the original
|
1803
1812
|
# file permissions and the current file permissions.
|
1804
1813
|
origperms = 0777
|
@@ -1813,17 +1822,15 @@ class Etch::Client
|
|
1813
1822
|
# Mask off the file type
|
1814
1823
|
fileperms = st.mode & 07777
|
1815
1824
|
end
|
1816
|
-
|
1817
1825
|
histperms = origperms & fileperms
|
1818
|
-
|
1819
|
-
File.
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
|
1825
|
-
|
1826
|
-
File.chmod(histperms, histrcspath) if (!@dryrun)
|
1826
|
+
|
1827
|
+
if File.directory?(histdir)
|
1828
|
+
Dir.foreach(histdir) do |histfile|
|
1829
|
+
next if histfile == '.'
|
1830
|
+
next if histfile == '..'
|
1831
|
+
File.chmod(histperms, File.join(histdir, histfile)) if (!@dryrun)
|
1832
|
+
end
|
1833
|
+
end
|
1827
1834
|
end
|
1828
1835
|
|
1829
1836
|
def get_local_requests(file)
|
@@ -2202,8 +2209,10 @@ class Etch::Client
|
|
2202
2209
|
# Note that cp -p will follow symlinks. GNU cp has a -d option to
|
2203
2210
|
# prevent that, but Solaris cp does not, so we resort to cpio.
|
2204
2211
|
# GNU cpio has a --quiet option, but Solaris cpio does not. Sigh.
|
2212
|
+
# GNU find and cpio also have -print0/--null to handle filenames with
|
2213
|
+
# spaces or special characters, but that's not standard either.
|
2205
2214
|
system("cd #{sourcedir} && find #{sourcefile} | cpio -pdum #{destdir}") or
|
2206
|
-
raise "
|
2215
|
+
raise "Recursive copy #{sourcedir}/#{sourcefile} to #{destdir} failed"
|
2207
2216
|
end
|
2208
2217
|
def recursive_copy_and_rename(sourcedir, sourcefile, destname)
|
2209
2218
|
tmpdir = tempdir(destname)
|
@@ -2211,7 +2220,17 @@ class Etch::Client
|
|
2211
2220
|
File.rename(File.join(tmpdir, sourcefile), destname)
|
2212
2221
|
Dir.delete(tmpdir)
|
2213
2222
|
end
|
2214
|
-
|
2223
|
+
def nonrecursive_copy(sourcedir, sourcefile, destdir)
|
2224
|
+
system("cd #{sourcedir} && echo #{sourcefile} | cpio -pdum #{destdir}") or
|
2225
|
+
raise "Non-recursive copy #{sourcedir}/#{sourcefile} to #{destdir} failed"
|
2226
|
+
end
|
2227
|
+
def nonrecursive_copy_and_rename(sourcedir, sourcefile, destname)
|
2228
|
+
tmpdir = tempdir(destname)
|
2229
|
+
nonrecursive_copy(sourcedir, sourcefile, tmpdir)
|
2230
|
+
File.rename(File.join(tmpdir, sourcefile), destname)
|
2231
|
+
Dir.delete(tmpdir)
|
2232
|
+
end
|
2233
|
+
|
2215
2234
|
def lock_file(file)
|
2216
2235
|
lockpath = File.join(@lockbase, "#{file}.LOCK")
|
2217
2236
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: etch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Heiss
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-20 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -36,12 +36,9 @@ files:
|
|
36
36
|
- bin/etch
|
37
37
|
- bin/etch_cron_wrapper
|
38
38
|
- bin/etch_to_trunk
|
39
|
-
- etc/ca.pem
|
40
|
-
- etc/dhparams
|
41
39
|
- lib/etch.rb
|
42
40
|
- lib/etchclient.rb
|
43
41
|
- lib/versiontype.rb
|
44
|
-
- man/man8/etch.8
|
45
42
|
- Rakefile
|
46
43
|
has_rdoc: true
|
47
44
|
homepage: http://etch.sourceforge.net
|
@@ -67,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
64
|
requirements: []
|
68
65
|
|
69
66
|
rubyforge_project: etchsyscm
|
70
|
-
rubygems_version: 1.3.
|
67
|
+
rubygems_version: 1.3.5
|
71
68
|
signing_key:
|
72
69
|
specification_version: 3
|
73
70
|
summary: Etch system configuration management client
|
data/etc/ca.pem
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# Add your SSL certificate authority's cert(s) to this file
|
data/etc/dhparams
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
-----BEGIN DH PARAMETERS-----
|
2
|
-
MIIBCAKCAQEA3HySq1WdL67BCSRCJCZYMUIojAWAsvK63D3cOGk0wI9UeM/yeVhz
|
3
|
-
jTswvHOVPZFKIBg1Aeo2eAEdPryDnmjVTgvLbuWkCPouQhBCVsQ1El9ZcXPix1rC
|
4
|
-
tYsg4Kll1jgnwFoHf4xvjPnD/SqsASAiDxYlh4CFVyT1gLgSiUU0rIdudgO3agI5
|
5
|
-
NgiyGOKwyHmNOOQSKA62M/JnoxcBDC7Nou3lqtHpR5yWsUz+csyk+hXZeUba97bm
|
6
|
-
M8OB0PmfK4Vo6JpdO+yc8hjeYBoMsH7g/l3Gm1JqUxxctcY/OuJ+2nkXwsD66E3D
|
7
|
-
yZCoiVd3u4OqAxNO/GG0iUmskjIvokMhUwIBAg==
|
8
|
-
-----END DH PARAMETERS-----
|
9
|
-
|
data/man/man8/etch.8
DELETED
@@ -1,204 +0,0 @@
|
|
1
|
-
.TH etch 8 "October 2009"
|
2
|
-
|
3
|
-
.SH NAME
|
4
|
-
|
5
|
-
.B etch
|
6
|
-
\- Configuration management for Unix systems
|
7
|
-
|
8
|
-
.SH SYNOPSIS
|
9
|
-
|
10
|
-
.B etch
|
11
|
-
.RB [ --generate-all ]
|
12
|
-
.RB [ --dry-run | \-n ]
|
13
|
-
.RB [ --damp-run ]
|
14
|
-
.RB [ --interactive ]
|
15
|
-
.RB [ --full-file ]
|
16
|
-
.RB [ --filename-only ]
|
17
|
-
.RB [ --disable-force ]
|
18
|
-
.RB [ --lock-force ]
|
19
|
-
.RB [ --debug ]
|
20
|
-
.RB [ --local
|
21
|
-
.IR DIR ]
|
22
|
-
.RB [ --server
|
23
|
-
.IR SERVER ]
|
24
|
-
.RB [ --tag
|
25
|
-
.IR TAG ]
|
26
|
-
.RB [ --test-base
|
27
|
-
.IR TESTDIR ]
|
28
|
-
.RB [ --key
|
29
|
-
.IR PRIVATE_KEY ]
|
30
|
-
.RB [ --version ]
|
31
|
-
.RB [ --help | \-h ]
|
32
|
-
.RI [ "file ..." ]
|
33
|
-
|
34
|
-
.SH DESCRIPTION
|
35
|
-
|
36
|
-
Etch is a tool for managing the configuration of Unix systems. Etch can manage
|
37
|
-
text or binary files, links and directories. The contents of files can be
|
38
|
-
supplied from static files or generated on the fly by scripts or templates.
|
39
|
-
Permissions and ownership as well as any pre or post commands to run when
|
40
|
-
updating the file are configured in simple XML files.
|
41
|
-
|
42
|
-
.SH OPTIONS
|
43
|
-
.TP
|
44
|
-
.B --generate-all
|
45
|
-
Request that the server generate and send over all available configuration.
|
46
|
-
Can be used instead of specifying specific files to request.
|
47
|
-
.TP
|
48
|
-
.B --dry-run | \-n
|
49
|
-
.B etch
|
50
|
-
will not make any changes to the system. Contents of generated config
|
51
|
-
files are displayed instead of being written to disk.
|
52
|
-
.TP
|
53
|
-
.B --damp-run
|
54
|
-
Perform an almost dry run, except that 'setup' entries for files are run.
|
55
|
-
Normally all setup/pre/post entries are ignored for a dry run. However, files
|
56
|
-
with setup entries will generally fail to build properly if the setup entry
|
57
|
-
hasn't been run. This allows you to preview the full and correct
|
58
|
-
configuration while making minimal changes to the system.
|
59
|
-
.TP
|
60
|
-
.B --interactive
|
61
|
-
Causes
|
62
|
-
.B etch
|
63
|
-
to pause before making each change and prompt the user for
|
64
|
-
confirmation.
|
65
|
-
.TP
|
66
|
-
.B --full-file
|
67
|
-
Normally
|
68
|
-
.B etch
|
69
|
-
will print a diff to show what changes it will make to a file. This will cause
|
70
|
-
.B etch
|
71
|
-
to display the full new file contents instead. Useful if the diff is hard to
|
72
|
-
read for a particular file.
|
73
|
-
.TP
|
74
|
-
.B --filename-only
|
75
|
-
Normally
|
76
|
-
.B etch
|
77
|
-
will print a diff to show what changes it will make to a file. This will cause
|
78
|
-
etch to display only the name of file to be changed. Useful on the initial
|
79
|
-
run during your system build process or other times when you want less output.
|
80
|
-
.TP
|
81
|
-
.B --disable-force
|
82
|
-
Ignore the disable_etch file. Use with caution. Typically used with
|
83
|
-
--interactive or --dry-run to evaluate what would happen if etch were
|
84
|
-
re-enabled.
|
85
|
-
.TP
|
86
|
-
.B --lock-force
|
87
|
-
.B Etch
|
88
|
-
does per-file internal locking as it runs to prevent problems with
|
89
|
-
simultaneous instances of the
|
90
|
-
.B etch
|
91
|
-
client stepping on each other.
|
92
|
-
.B Etch
|
93
|
-
automatically cleans up lockfiles over two hours old on the assumption that
|
94
|
-
any lockfiles that old were left behind by a previous instance that failed for
|
95
|
-
some (hopefully transient) reason. In a large environment you don't want to
|
96
|
-
have to run around manually cleaning up lockfiles every time a full disk or
|
97
|
-
unavailable package server or other transient failure causes
|
98
|
-
.B etch
|
99
|
-
to fail
|
100
|
-
temporarily. This option forces the removal of any existing lockfiles no
|
101
|
-
matter how old. Useful if a buggy configuration or local environmental issue
|
102
|
-
caused
|
103
|
-
.B etch
|
104
|
-
to abort and you want to immediately retry.
|
105
|
-
.TP
|
106
|
-
.BI --local " DIR"
|
107
|
-
Read configuration from a local directory rather than requesting it from
|
108
|
-
a server.
|
109
|
-
.TP
|
110
|
-
.BI --server " SERVER"
|
111
|
-
Point
|
112
|
-
.B etch
|
113
|
-
to an alternate server, specified in the form of a URL.
|
114
|
-
.TP
|
115
|
-
.BI --tag " TAG"
|
116
|
-
Request a specific repository tag from the server. Tags are directory paths
|
117
|
-
relative to /etc/etchserver by default. Thus examples might be
|
118
|
-
.I trunk
|
119
|
-
for /etc/etchserver/trunk, or
|
120
|
-
.I branches/mytestbranch
|
121
|
-
for /etc/etchserver/branches/mytestbranch.
|
122
|
-
.TP
|
123
|
-
.BI --key " PRIVATE_KEY"
|
124
|
-
Use an alternate SSH private key file for signing messages that are sent to
|
125
|
-
the server.
|
126
|
-
.TP
|
127
|
-
.BI --test-base " TESTDIR"
|
128
|
-
Use an alternate local working directory instead of /var/etch. Generally only
|
129
|
-
used for allowing the etch test suite to be run as a non-root user.
|
130
|
-
.TP
|
131
|
-
.B --debug
|
132
|
-
Print lots of messages about what etch is doing.
|
133
|
-
.TP
|
134
|
-
.B --version
|
135
|
-
Show the etch client version and exit.
|
136
|
-
.TP
|
137
|
-
.B --help | \-h
|
138
|
-
Display the etch usage message and exit.
|
139
|
-
|
140
|
-
.SH FILES
|
141
|
-
|
142
|
-
.TP
|
143
|
-
.B /etc/etch/ca.pem
|
144
|
-
SSL certificate(s) needed to verify the
|
145
|
-
.B etch
|
146
|
-
server's identity. If
|
147
|
-
.B etch
|
148
|
-
is using a server with an https:// URL and if this file exists then
|
149
|
-
.B etch
|
150
|
-
will not proceed if the server's SSL certificate can't be verified against the
|
151
|
-
certs in this file.
|
152
|
-
.TP
|
153
|
-
.B /etc/etch/dhparams
|
154
|
-
The Diffie-Hellman parameters used as part of the SSL connection process. Etch
|
155
|
-
comes with a set and there's no need to generate your own, but a new set can
|
156
|
-
be generated via "openssl dhparam" if desired. If this file is not present the
|
157
|
-
Ruby SSL library will warn that it is using its internal default set of
|
158
|
-
parameters.
|
159
|
-
.TP
|
160
|
-
.B /var/etch/disable_etch
|
161
|
-
If this file is present
|
162
|
-
.B etch
|
163
|
-
will do nothing other than send a message to the
|
164
|
-
.B etch
|
165
|
-
server that it is disabled. Any text in this file will be included in
|
166
|
-
that message to the server and displayed locally. If you are disabling
|
167
|
-
.B etch
|
168
|
-
always put a note in this file indicating who you are, today's date, and why
|
169
|
-
you are disabling
|
170
|
-
.B etch
|
171
|
-
so that fellow administrators won't have to guess later why
|
172
|
-
.B etch
|
173
|
-
was disabled. Re-enabling
|
174
|
-
.B etch
|
175
|
-
after it has been disabled for a long
|
176
|
-
time can be time-consuming, as the person doing so must review any potential
|
177
|
-
changes that have been queued up and ensure that they won't interfere with the
|
178
|
-
current usage of the system. As such be thoughtful about whether disabling
|
179
|
-
.B etch
|
180
|
-
is necessary, and re-enable it as soon as possible.
|
181
|
-
.TP
|
182
|
-
.B /var/etch/history
|
183
|
-
A revision history of each
|
184
|
-
.B etch
|
185
|
-
managed file, stored using the RCS revision control system.
|
186
|
-
.TP
|
187
|
-
.B /var/etch/locks
|
188
|
-
Directory used by the
|
189
|
-
.B etch
|
190
|
-
internal locking mechanism. See the --lock-force option for more details.
|
191
|
-
.TP
|
192
|
-
.B /var/etch/orig
|
193
|
-
A backup of the original contents of each
|
194
|
-
.B etch
|
195
|
-
managed file as it was before etch first touched it.
|
196
|
-
|
197
|
-
.SH DIAGNOSTICS
|
198
|
-
|
199
|
-
See the --debug option and the server logs.
|
200
|
-
|
201
|
-
.SH AUTHOR
|
202
|
-
|
203
|
-
.B Etch
|
204
|
-
is designed and maintained by Jason Heiss
|