fixes first boot kernel-issues

This commit is contained in:
Denis Knauf 2019-10-26 12:28:17 +02:00
parent ec88e37571
commit 6aee21c7ca
9 changed files with 320 additions and 108 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.*.sw[po]

3
README.adoc Normal file
View file

@ -0,0 +1,3 @@
= Dependencies =
sudo aptitude install git kpartx ruby qemu-system-arm qemu-user-static

91
init.sh Normal file
View file

@ -0,0 +1,91 @@
#!/bin/sh -e
Usage() {
>&2 echo "Usage: $0 hostname [vgname]"
exit 1
}
die() {
>&2 echo "died: $*"
exit 1
}
msg() {
>&2 printf '\e[34;1m%s\e[0m\n' "$*"
}
lv_exists() {
true && lvs --noheadings --options lv_name "$1"
case $? in
0) return 0 ;;
5) return 1 ;;
*) die "Error while determining, if lv «$1» exists" ;;
esac
}
alias blkuuid="blkid -ovalue -sUUID" blkfstype="blkid -ovalue -sTYPE"
[ X = X"$1" ] && Usage
[ X-h = X"$1" ] && Usage
[ X--help = X"$1" ] && Usage
hostname="$1"
#vgname="${2:-${hostname}sd}"
disc="/dev/mmcblk1"
pvpath="${disc}p2"
echo "Hostname: «$hostname»"
#echo "VG-name: «$vgname»"
echo
msg "Install needed tools..."
apt update
apt install -y lvm2 xfsprogs
msg "Set Hostname «$hostname»..."
oldhostname=`cat /etc/hostname`
sed -i -e "s/$oldhostname/$hostname/g" /etc/hosts
echo "$hostname" > /etc/hostname
vgname="`pvs --noheadings --options vg_name "$pvpath" | sed -e 's/^ *//'`"
# renaming does not work, because blockdevices will not be created.
# vgknodes, vgscan --mknodes tested.
#if [ "X$oldvgname" = "X$vgname" ]
#then
# msg "VG already named «$vgname»."
#else
# msg "Rename VG in «$vgname»..."
# vgrename "$oldvgname" "$vgname"
#fi
msg "Expand PV «$pvpath»..."
parted -ms "$disc" -- resizepart 2 -4MB print
pvresize "$pvpath"
msg "Expand root-LV..."
lvextend -rL4G "$vgname/root"
if lv_exists "$vgname/swap"
then
msg "LV «swap» already exists."
else
msg "Prepare swap-LV..."
lvcreate -nswap -L2G "$vgname"
mkswap "/dev/$vgname/swap"
echo "UUID=`blkuuid /dev/$vgname/swap` swap swap sw 0 0" >>/etc/fstab
fi
if lv_exists "$vgname/home"
then
msg "LV «home» already exists"
else
msg "Prepare home-LV..."
lvcreate -nhome -L4G "$vgname"
mkfs.xfs "/dev/$vgname/home"
echo "UUID=`blkuuid /dev/$vgname/home` /home xfs defaults 0 0" >>/etc/fstab
fi
msg "Install Updates..."
apt dist-upgrade -y
msg "ok"

View file

@ -32,7 +32,7 @@ class Base
end end
def lpartx image def lpartx image
mapper = Pathname.new '/dev/mapper' mapper = XPathname.new '/dev/mapper'
lines = sh.kpartx( -:al, image, return: :lines)[0..-1] lines = sh.kpartx( -:al, image, return: :lines)[0..-1]
if lines.grep( /^loop deleted/).empty? if lines.grep( /^loop deleted/).empty?
lines.map do |line| lines.map do |line|
@ -138,16 +138,17 @@ Settings:
EOF EOF
sh.def_system_commands *%i[echo sed mount umount kpartx sync rsync xz gzip bzip2 zip tar bash dpkg apt] sh.def_system_commands *%i[echo sed mount umount kpartx sync rsync xz gzip bzip2 zip tar bash dpkg apt]
sh.def_system_commands *%i[dmsetup lvcreate vgcreate pvcreate vgchange mkswap vgscan] sh.def_system_commands *%i[losetup dmsetup lvcreate vgcreate pvcreate vgchange mkswap vgscan]
sh.alias_command :losetup_list, *%w[losetup --list --json], return: :json, could_be_empty: true
sh.alias_command :pvs, *%w[pvs --noheadings] sh.alias_command :pvs, *%w[pvs --noheadings]
sh.alias_command :blkid, 'blkid', return: :line sh.alias_command :blkid, 'blkid', return: :line
sh.alias_command :lsblk, *%w[lsblk --noheadings --paths --list], return: :lines sh.alias_command :lsblk, *%w[lsblk --noheadings --paths --list], return: :lines
sh.alias_command :parted, *%w[parted -ms] sh.alias_command :parted, *%w[parted --machine --script]
sh.alias_command :mkxfs, *%w[mkfs.xfs -f] sh.alias_command :mkxfs, *%w[mkfs.xfs -f]
sh.alias_command :mkext2fs, *%w[mkfs.ext2] sh.alias_command :mkext2fs, *%w[mkfs.ext2]
sh.alias_command :mkext4fs, *%w[mkfs.ext4] sh.alias_command :mkext4fs, *%w[mkfs.ext4]
sh.alias_command :mkvfat, *%w[mkfs.vfat] sh.alias_command :mkvfat, *%w[mkfs.vfat]
sh.alias_command :rsync_all, *%w[rsync -aHAX] sh.alias_command :rsync_all, *%w[rsync --archive --hard-links --acls --xattrs]
sh.alias_command :mount_ro, *%w[mount -oro] sh.alias_command :mount_ro, *%w[mount -oro]
sh.alias_command :fs_uuid, *%w[blkid -o value -s UUID], return: :line sh.alias_command :fs_uuid, *%w[blkid -o value -s UUID], return: :line
sh.alias_command :fs_type, *%w[blkid -o value -s TYPE], return: :line sh.alias_command :fs_type, *%w[blkid -o value -s TYPE], return: :line
@ -188,19 +189,20 @@ EOF
end end
opts.on '-aAUTHKEYS', '--auth-keys=AUTHKEYS', 'SSH-Keys for user' do |f| opts.on '-aAUTHKEYS', '--auth-keys=AUTHKEYS', 'SSH-Keys for user' do |f|
f = Pathname.new f f = XPathname.new f
d "#{f} not found.", f.exist? d "#{f} not found.", f.exist?
@authorized_keys = f @authorized_keys = f
end end
opts.on '-AAUTHKEYS', '--root-auth-keys=AUTHKEYS', 'SSH-Keys for root' do |f| opts.on '-AAUTHKEYS', '--root-auth-keys=AUTHKEYS', 'SSH-Keys for root' do |f|
f = Pathname.new f f = XPathname.new f
d "#{f} not found.", f.exist? d "#{f} not found.", f.exist?
@root_authorized_keys = f @root_authorized_keys = f
end end
end end
def run def run
nok = false
build build
qemu_bin = dest.root + "usr/bin/qemu-arm-static" qemu_bin = dest.root + "usr/bin/qemu-arm-static"
@ -210,10 +212,11 @@ EOF
end end
rescue ProgrammError rescue ProgrammError
nok = true
err $! err $!
raise raise
ensure ensure
STDERR.puts "="*80 STDERR.puts "\e[1;36m#{"<"*80}\e[0m"
umount_all ignore_exceptions: true umount_all ignore_exceptions: true
umount dest.root, -:R rescue Object umount dest.root, -:R rescue Object
umount base.root, -:R rescue Object umount base.root, -:R rescue Object
@ -222,7 +225,7 @@ EOF
departx dest.image rescue Object departx dest.image rescue Object
departx base.image rescue Object departx base.image rescue Object
sh.sync rescue Object sh.sync rescue Object
STDERR.puts "="*80 STDERR.puts "\e[1;#{nok ? 31: 36}m#{">"*80}\e[0m"
end end
def activate_vg vgname def activate_vg vgname
@ -283,66 +286,61 @@ EOF
end end
def ssh_copy_id_local src, home, uid, gid = nil def ssh_copy_id_local src, home, uid, gid = nil
akf = home+'.ssh/authorized_keys' akfile = home+'.ssh/authorized_keys'
akd = akf.dirname akdir = akfile.dirname
akd.mkdir akdir. mkdir
akd.chown uid, gid akdir. chown uid, gid
akd.chmod 0700 akdir. chmod 0700
akf.copy src akfile.copy src
akf.chown uid, gid akfile.chown uid, gid
akf.chmod 0600 akfile.chmod 0600
end end
def rename_user def install_authorized_keys
ssh_copy_id_local @authorized_keys, dest.root+'home/pi', 1000, 1000 if @authorized_keys ssh_copy_id_local @authorized_keys, dest.root+'home/pi', 1000, 1000 if @authorized_keys
ssh_copy_id_local @root_authorized_keys, dest.root+'root', 0, 0 if @root_authorized_keys ssh_copy_id_local @root_authorized_keys, dest.root+'root', 0, 0 if @root_authorized_keys
end
if @username def rename_user username = nil, password: nil, old: nil
dest.root.join( 'etc/passwd').replace_i do |f| username ||= @username
f.each_line.flat_map do |l| old ||= 'pi'
user, pwd, uid, gid, name, home, shell = l.split( ':') password ||= @password
user, home = @username, "/home/#{@username}" if 'pi' == user
if username and old != username
dest.root.join( 'etc/passwd').sed_i do |l|
user, pwd, uid, gid, name, home, shell = l.split( ':', 7)
user, home = username, "/home/#{username}" if old == user
[user, pwd, uid, gid, name, home, shell].join ':' [user, pwd, uid, gid, name, home, shell].join ':'
end end
end
dest.root.join( 'etc/group').replace_i do |f| dest.root.join( 'etc/group').sed_i do |l|
f.each_line.flat_map do |l| group, pwd, gid, users = l.split( ':', 4)
group, pwd, gid, users = l.split( ':') group = username if old == group
group = @username if 'pi' == group users = users.split( ',').map {|user| old == user ? username : user }
users = users.split( ',').map {|user| 'pi' == user ? @username : user }
[group, pwd, gid, users.join( ',')].join ':' [group, pwd, gid, users.join( ',')].join ':'
end end
dest.root.join( 'home', old).rename dest.root.join( 'home', username)
end end
dest.root.join( 'home/pi').rename dest.root.join( 'home', @username) if password or username
end dest.root.join( 'etc/shadow').sed_i do |l|
user, crypt, lastchange, minage, maxage, warn, inact, expiry, reserved = l.split( ':', 9)
if @password or @username if old == user
dest.root.join( 'etc/shadow').replace_i do |f| crypt = password if password
f.each_line.flat_map do |l| user = username if username
user, crypt, lastchange, minage, maxage, warn, inact, expiry, reserved = l.split( ':')
if 'pi' == user
crypt = @password if @password
user = @username if @username
end end
[user, crypt, lastchange, minage, maxage, warn, inact, expiry, reserved].join ':' [user, crypt, lastchange, minage, maxage, warn, inact, expiry, reserved].join ':'
end end
end end
end end
end
def set_hostname hostname = nil def set_hostname hostname = nil
hostname = @hostname hostname ||= @hostname
return if hostname.nil? or hostname.empty? return if hostname.nil? or hostname.empty?
msg :patch, 'etc/hosts', 'set hostname to', hostname msg "setting hostname", hostname
dest.root.join( 'etc/hosts').replace_i do |f| dest.root.join( 'etc/hosts').sed_i {|l| l.gsub /\<raspberrypi\>/, hostname }
f.each_line.map {|l| l.gsub /\<raspberrypi\>/, hostname } dest.root.join( 'etc/hostname').write "#{hostname}\n"
end
msg :write, hostname, :to, 'etc/hostname'
dest.root.join( 'etc/hostname').open 'w' do |f|
f.puts hostname
end
end end
def install_packages_from_dir *paths def install_packages_from_dir *paths
@ -368,7 +366,7 @@ EOF
def install_deb path def install_deb path
#sh.dpkg '--unpack', '--force-architecture', pn, chroot: dest.root #sh.dpkg '--unpack', '--force-architecture', pn, chroot: dest.root
adeb = Pathname.new( 'var/cache/apt/archives')+path.basename.to_s adeb = XPathname.new( 'var/cache/apt/archives')+path.basename.to_s
dest.root.join( adeb.to_s).copy path dest.root.join( adeb.to_s).copy path
sh.dpkg -:i, adeb, chroot: dest.root sh.dpkg -:i, adeb, chroot: dest.root
#msg :unpack, path #msg :unpack, path

View file

@ -1,7 +1,9 @@
require 'pathname' require 'pathname'
class Pathname class Pathname
alias +@ to_s def +@
expand_path.to_s
end
def chdir &exe def chdir &exe
Dir.chdir self.to_s, &exe Dir.chdir self.to_s, &exe
@ -13,6 +15,14 @@ class Pathname
FileUtils.copy_file src.to_s, self.to_s, **opts FileUtils.copy_file src.to_s, self.to_s, **opts
end end
def symlink to
File.symlink to.to_s, to_s
end
def link to
File.link to.to_s, to_s
end
def replace_i def replace_i
open 'r+' do |f| open 'r+' do |f|
lines = yield f lines = yield f
@ -21,6 +31,67 @@ class Pathname
f.puts lines f.puts lines
end end
end end
def sed_i **replaces, &e
open 'r+' do |f|
lines = f.each_line.flat_map {|l| yield l.chomp, replaces }
f.truncate 0
f.pos = 0
f.puts lines
replaces.each {|_,rls| f.puts rls }
end
end
end
class XPathname < Pathname
%i[/ + join].each do |meth|
define_method meth do |*n|
XPathname.new "#{super *n}"
end
end
%i[unlink read].each do |meth|
define_method meth do |*a, &e|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m"
super *a, &e
end
end
%i[replace_i sed_i].each do |meth|
define_method meth do |*a, &e|
STDERR.puts "\e[1;36mpatching \e[1;35m#{self}\e[0m"
super *a, &e
end
end
%i[link rename symlink].each do |meth|
define_method meth do |*a, &e|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m -> #{a.map{|x|"\e[1;35m#{x}\e[0m"}.join ', '}"
super *a, &e
end
end
%i[move copy].each do |meth|
define_method meth do |*a, &e|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m <- #{a.map{|x|"\e[1;35m#{x}\e[0m"}.join ', '}"
super *a, &e
end
end
%i[make_link make_symlink].each do |meth|
name = meth.to_s.sub /\Amake_/, ''
define_method meth do |*a, &e|
STDERR.puts "\e[1;36m#{name} \e[1;35m#{self}\e[0m -> #{a.map{|x|"\e[1;35m#{x}\e[0m"}.join ', '}"
super *a, &e
end
end
%i[write].each do |meth|
define_method meth do |*a, &e|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m \e[1;35m#{a[0][0...128].inspect}\e[0m"
super *a, &e
end
end
end end
class Symbol class Symbol

View file

@ -10,9 +10,23 @@ class Raspbian < Base
ENV['LANG'] = 'C' ENV['LANG'] = 'C'
mkmppaths mkmppaths
case
when !dest.image.exist?
when dest.image.file?
r = sh.losetup_list
unless r.empty? or r['loopdevices']
r['loopdevices'].each do |lo|
d "File #{dest.image} used as loop-device back-file",
+dest.image != +XPathname.new(lo['back-file'])
end
end
when dest.image.blockdev?, dest.image.chardev?
lsblk( dest.image).each do |l| lsblk( dest.image).each do |l|
d "Device #{l[:name]} mounted at #{l[:mountpoint]}", ! l[:mountpoint] d "Device #{l[:name]} mounted at #{l[:mountpoint]}", ! l[:mountpoint]
end end
end
sleep 5
d "Base image does not exist", base.image.exist? d "Base image does not exist", base.image.exist?
base_parts = kpartx base.image base_parts = kpartx base.image
@ -38,7 +52,7 @@ class Raspbian < Base
STDERR.puts l STDERR.puts l
sh.dmsetup :remove, File.basename(l[:name]) if 'lvm' == l[:type] sh.dmsetup :remove, File.basename(l[:name]) if 'lvm' == l[:type]
l[:name].start_with?( dest.image.to_s) and 'part' == l[:type] l[:name].start_with?( dest.image.to_s) and 'part' == l[:type]
end.map {|l| Pathname.new l[:name] }.sort end.map {|l| XPathname.new l[:name] }.sort
rescue Sh::ProcessError rescue Sh::ProcessError
kpartx dest.image kpartx dest.image
end end
@ -46,8 +60,8 @@ class Raspbian < Base
dest_parts[0].open( 'w') {|f| f << 0.chr*4*1024*1024 } dest_parts[0].open( 'w') {|f| f << 0.chr*4*1024*1024 }
dest_parts[1].open( 'w') {|f| f << 0.chr*4*1024*1024 } dest_parts[1].open( 'w') {|f| f << 0.chr*4*1024*1024 }
sh.vgscan '--cache' sh.vgscan '--cache'
vgpath = Pathname.new( '/dev') + vgname vgpath = XPathname.new( '/dev') + vgname
sh.pvcreate '-ff', dest_parts[1] sh.pvcreate -:ff, dest_parts[1]
sh.vgcreate vgname, dest_parts[1] sh.vgcreate vgname, dest_parts[1]
sh.lvcreate -:nroot, '-L4.2G', vgname sh.lvcreate -:nroot, '-L4.2G', vgname
sh.lvcreate -:nhome, '-L100M', vgname sh.lvcreate -:nhome, '-L100M', vgname
@ -56,7 +70,7 @@ class Raspbian < Base
sh.mkxfs -:Lroot, vgpath+'root' sh.mkxfs -:Lroot, vgpath+'root'
sh.mkxfs -:Lhome, vgpath+'home' sh.mkxfs -:Lhome, vgpath+'home'
mount vgpath+'root', dest.root mount vgpath+'root', dest.root
addmp = {} addmp = {run_udev: dest.root+'run/udev'}
%i[home boot dev proc sys].each do |n| %i[home boot dev proc sys].each do |n|
d = addmp[n] = dest.root+n.to_s d = addmp[n] = dest.root+n.to_s
d.mkdir d.mkdir
@ -69,11 +83,10 @@ class Raspbian < Base
mount 'sysfs', addmp[:sys], -:tsysfs mount 'sysfs', addmp[:sys], -:tsysfs
sh.rsync_all "#{base.root}/", dest.root sh.rsync_all "#{base.root}/", dest.root
#sh.rsync *%w[kernel7.img initrd7.img], addmp[:boot]
install_authorized_keys
rename_user rename_user
msg :patch, 'etc/fstab'
(dest.root+'etc'+'fstab').replace_i do |f| (dest.root+'etc'+'fstab').replace_i do |f|
replace = { replace = {
'/' => "UUID=#{sh.fs_uuid vgpath+'root'} / xfs defaults,noatime 0 0", '/' => "UUID=#{sh.fs_uuid vgpath+'root'} / xfs defaults,noatime 0 0",
@ -86,25 +99,34 @@ class Raspbian < Base
end + replace.values end + replace.values
end end
msg :patch, 'boot/config.txt'
(addmp[:boot]+'config.txt').replace_i do |f| (addmp[:boot]+'config.txt').replace_i do |f|
replace = { replace = {
initramfs: 'initramfs initrd7.img followkernel', 'pi4' => { initramfs: 'initramfs initrd7l.img followkernel', },
'pi3' => { initramfs: 'initramfs initrd7.img followkernel', },
'pi2' => { initramfs: 'initramfs initrd7.img followkernel', },
'pi1' => { initramfs: 'initramfs initrd.img followkernel', },
'pi0' => { initramfs: 'initramfs initrd.img followkernel', },
} }
f.each_line.flat_map do |l| blocks = [nil]
content = Hash.new {|h,block| h[block] = [] }
block = nil
f.each_line do |l|
l.chomp! l.chomp!
case l case l
when /^initramfs / when /\A\[([^\]]*)\]\z/
replace.delete :initramfs block = $1
else l blocks.push block
when /\Ainitramfs /
l = replace[block].delete :initramfs
end end
end + replace.values content[block].push l
end
replace.each {|block, rpl| content[block] += rpl.values + [''] unless rpl.empty? }
blocks.flat_map {|block| content[block] }
end end
msg :touch, 'boot/ssh' (addmp[:boot]+'ssh').write ''
(addmp[:boot]+'ssh').open('w') {|f|}
msg :patch, 'boot/cmdline.txt'
(addmp[:boot]+'cmdline.txt').replace_i do |f| (addmp[:boot]+'cmdline.txt').replace_i do |f|
lines = f.readlines lines = f.readlines
d "Only one line in cmdline.txt expected", 1 == lines.length d "Only one line in cmdline.txt expected", 1 == lines.length
@ -119,46 +141,58 @@ class Raspbian < Base
opts.map {|k,v| v ? "#{k}=#{v}" : "#{k}" }.join(' ') opts.map {|k,v| v ? "#{k}=#{v}" : "#{k}" }.join(' ')
end end
msg :patch, 'etc/initramfs-tools/initramfs.conf'
dest.root.join( 'etc/initramfs-tools/initramfs.conf').replace_i do |f|
f.each_line.flat_map do |l|
l.chomp!
case l
when /^COMPRESS=/
'COMPRESS=xz'
when /^# *COMPRESS=/
[l, 'COMPRESS=xz']
else
l
end
end
end
set_hostname
msg :unlinking, 'etc/rc*.d/*resize2fs_once'
(dest.root+'etc').chdir do (dest.root+'etc').chdir do
Pathname.glob( 'rc*.d/*resize2fs_once').each do |fn| XPathname.glob( 'rc*.d/*resize2fs_once').each do |fn|
fn.unlink fn.unlink
end end
end end
qemu_bin = dest.root.join 'usr/bin/qemu-arm-static' qemu_bin = dest.root.join 'usr/bin/qemu-arm-static'
msg :copy, "/usr/bin/qemu-arm-static"
qemu_bin.copy '/usr/bin/qemu-arm-static', preserve: true qemu_bin.copy '/usr/bin/qemu-arm-static', preserve: true
preload, preload_x = dest.root+'etc/ld.so.preload', dest.root+'etc/ld.so.preload.tp'
preload.rename preload_x
ish = sh.chroot( dest.root).chdir( '/') ish = sh.chroot( dest.root).chdir( '/')
ish.apt :update ish.apt :update
ish.apt :upgrade, -:y ish.apt :upgrade, -:y
ish.apt :update ish.apt :update
ish.apt :install, -:y, :lvm2, :xfsprogs
# We mount /run/udev for lvm-scanning - vgs / vgcfgbackup need it to connect to udev.
addmp[:run_udev].mkdir
mount '/run/udev', addmp[:run_udev], --:bind
# prevent installing exim by installing nullmailer
#ish.apt :install, -:y, :lvm2, :xfsprogs, :nullmailer, :dracut
#dest.root.join( 'etc/dracut.conf.d/10-denkn.conf').open 'w' do |f|
# f.puts 'add_modules+="lvm"'
# f.puts 'add_drivers+="dm-mod xfs"'
# f.puts 'compress="xz"'
#end
ish.apt :install, -:y, :lvm2, :xfsprogs, 'initramfs-tools'
dest.root.join( 'etc/initramfs-tools/initramfs.conf').replace_i do |f|
replace = { compress: 'COMPRESS=xz', }
f.each_line.flat_map do |l|
case l.chomp!
when /^COMPRESS=/ then replace.delete :compress
when /^# *COMPRESS=/ then [l, replace.delete( :compress)]
else l
end
end + replace.values
end
set_hostname
install_packages_from_dir( install_packages_from_dir(
Pathname.new($0).expand_path.dirname+'raspbian-files', XPathname.new( $0).expand_path.dirname + 'raspbian-files',
Pathname.new('files') XPathname.new( 'files')
) )
# generates implicite initramfs # generates implicite initramfs
ish.system *%w[dpkg-reconfigure raspberrypi-kernel] ish.system *%w[dpkg-reconfigure raspberrypi-kernel]
preload_x.rename preload
qemu_bin.unlink
end end
end end

View file

@ -1,6 +1,7 @@
require 'forwardable' require 'forwardable'
require 'shellwords' require 'shellwords'
require 'socket' require 'socket'
require 'json'
class Sh class Sh
class ForkError < RuntimeError class ForkError < RuntimeError
@ -99,13 +100,14 @@ class Sh
if opts[:chroot] if opts[:chroot]
STDERR.printf "\e[1;34mchroot(%s)\e[0m ", opts[:chroot].to_s STDERR.printf "\e[1;34mchroot(%s)\e[0m ", opts[:chroot].to_s
Dir.chroot opts[:chroot].to_s Dir.chroot opts[:chroot].to_s
Dir.chdir '/'
end end
if @shell.opts[:pwd] if @shell.opts[:dir]
STDERR.printf "%s ", @shell.opts[:pwd] STDERR.printf "%s ", @shell.opts[:dir]
Dir.chdir @shell.opts[:pwd] Dir.chdir @shell.opts[:dir]
end end
#STDERR.puts "\e[0m#{opts[:return] ? '<=' : '#'} \e[33m#{cmd.shellescape} \e[35m#{usable_args.shelljoin}\e[0m" #STDERR.puts "\e[0m#{opts[:return] ? '<=' : '#'} \e[33m#{cmd.shellescape} \e[35m#{usable_args.shelljoin}\e[0m"
STDERR.printf "\e[0m%s \e[33m%s \e[35m%s\e[0m\n", STDERR.printf "\e[30;1m%s \e[0;33m%s \e[1;35m%s\e[0m\n",
opts[:return] ? '<=' : '#', opts[:return] ? '<=' : '#',
cmd.shellescape, cmd.shellescape,
usable_args.shelljoin usable_args.shelljoin
@ -132,7 +134,19 @@ class Sh
when :string when :string
opts[:mode], exe = :io, lambda( &:read) opts[:mode], exe = :io, lambda( &:read)
when :line when :line
opts[:mode], exe = :io, lambda{|f|f.read.chomp} opts[:mode], exe = :io, lambda {|f| f.read.chomp }
when :json
opts[:mode] = :io
if opts[:could_be_empty]
exe = lambda do |f|
r = f.read
r.empty? ? [] : JSON.parse( r)
end
else
exe = lambda {|f| JSON.parse f.read }
end
when :jsonl
opts[:mode], exe = :io, lambda {|f| f.each_line.map {|l| JSON.parse l } }
end end
r = f = fork **opts r = f = fork **opts
begin begin

View file

@ -7,13 +7,13 @@ class Image
@dir = @dir =
case dir case dir
when Pathname then dir when Pathname then dir
when String then Pathname.new dir when String then XPathname.new dir
else raise ArgumentError, "Pathname for dir expected" else raise ArgumentError, "Pathname for dir expected"
end end
@image = @image =
case image case image
when Pathname then image when Pathname then image
when String then Pathname.new image when String then XPathname.new image
when nil then @dir+'image' when nil then @dir+'image'
else raise ArgumentError, "Pathname for image expected" else raise ArgumentError, "Pathname for image expected"
end end
@ -21,7 +21,7 @@ class Image
@root = @root =
case root case root
when Pathname then root when Pathname then root
when String then Pathname.new root when String then XPathname.new root
when nil then @dir+'root' when nil then @dir+'root'
else raise ArgumentError, "Path for root must be Pathname, String or MP, if given" else raise ArgumentError, "Path for root must be Pathname, String or MP, if given"
end end

Binary file not shown.