10

I am trying to run the following preseed file on a ubuntu 16.04 server machine (during a packer build):

d-i preseed/late_command string \
in-target mkdir -v -p -m 0440 "/etc/sudoers.d"; \
in-target echo "%vagrant ALL=(ALL) NOPASSWD: ALL" | tee -a /etc/sudoers.d/vagrant; \
in-target echo "Defaults:vagrant !requiretty" | tee -a /etc/sudoers.d/vagrant; \
in-target chmod 440 /etc/sudoers.d/vagrant;

In /var/log/installer/syslog I can see the following error:

log-output: sh:
log-output: tee: not found

When I change the "| tee -a" part to ">>" like so:

d-i preseed/late_command string \
in-target mkdir -v -p -m 0440 "/etc/sudoers.d"; \
in-target echo "%vagrant ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/vagrant; \
in-target echo "Defaults:vagrant !requiretty" >> /etc/sudoers.d/vagrant; \
in-target chmod 440 /etc/sudoers.d/vagrant;

It suddenly starts complaining it cannot find the directory, without saying anything about the mkdir line - so it's neither creating the directory, nor not finding it:

log-output: sh: can't create /etc/sudoers.d/vagrant: nonexistent directory
log-output: sh: can't create /etc/sudoers.d/vagrant: nonexistent directory
log-output: chmod:
log-output: cannot access '/etc/sudoers.d/vagrant'
log-output: : No such file or directory

I have been looking into other scripts on github. Also I added the following line to the preseed.cfg file:

d-i pkgsel/include string openssh-server coreutils wget sudo

I even tried to install coreutils as in-target command, to make sure tee should be available. Been on this for a few days now, rebuilding ubuntu time after time, only to find the same errors in the syslog. If anyone could shed some light on this - it must be something simple, but I'm not seeing it...

6 Answers6

6

It doesn't seem to work to use echo into in-target. To solve this try the following (tried in Ubuntu 18.04):

d-i preseed/late_command string \
    echo "some text" >> /target/path/to/file.ext ; \
    in-target [some-other-command-in-target]

NOTE:

  • Don't use in-target before the line
  • Use /target before the real path
  • In other commands you can mostly use in-target before the line
Sander
  • 424
5

Two things:

  1. When doing in-target some_command > /some/path the redirection will NOT occur inside the target. You would need to do: in-target --pass-stdout some_command > /target/some/path

  2. The in-target command will redirect the output from the command to the logfile. So trying to redirect the output from in-target doesn't work by default. What you need to do is use the --pass-stdout argument to in-target

in-target --pass-stdout echo "hello" > /target/root/hello.txt

This will create a file /target/root/hello.txt with the content 'hello'

From: https://salsa.debian.org/installer-team/debian-installer-utils/-/blob/3e67bc7987eb4a9cdff5fe8d1084e612fe7bb48f/README

in-target: Runs the specified command in /target and returns its exit status. The debconf passthrough frontend is used to make debconf questions be asked using cdebconf in the installer. This is especially useful for running things like dpkg-reconfigure, debconf-apt-progress, and tasksel. The log-output utility is used to log any output; if in-target is called with the option --pass-stdout, log-output will respect it.

3

If you prefer to use debian installer, this worked for me on 17.10.1 server when adding an ssh public key to authorized_keys. You have to make sure the .ssh directory is created beforehand.

d-i preseed/late_command string in-target /bin/sh -c 'echo "my string" >> /home/username/.ssh/authorized_keys';

I spent about a day debugging this and tried the following with various results. It would be nice if there were more detailed documentation on which shell is used in debian installer for the various non / 'in-target' directives but I am probably not looking in right place.

  1. plain in-target echo with plain authorized_keys path:

    in-target echo "my string" >> /home/username/.ssh/authorized_keys;
    

    gives "directory not found" in /var/log/installer/syslog

  2. plain in-target echo with target authorized_keys path:

    in-target echo "my string" >> /target/home/username/.ssh/authorized_keys;
    

    produces a blank authorized_keys file on the target machine and when viewing /var/log/installer/syslog you find "my string" is output to stdout

  3. in-target with explicit sh -c... and target authorized_keys path:

    in-target /bin/sh -c 'echo "my string" >> /target/home/username/.ssh/authorized_keys';
    

    produces a "directory not found" error in /var/log/installer/syslog

Hopefully this saves a bit of time and debugging!

2

You can use Ubiquity instead of Debian-Installer (https://wiki.ubuntu.com/Installer/FAQ), so your command would be:

ubiquity  ubiquity/success_command string \
 in-target /bin/mkdir -v -p -m 0440 "/target/etc/sudoers.d"; \
 in-target /bin/echo "%vagrant ALL=(ALL) NOPASSWD: ALL" >> /target/etc/sudoers.d/vagrant; \
 in-target /bin/echo "Defaults:vagrant !requiretty" >> /target/etc/sudoers.d/vagrant; \
 in-target /bin/chmod 440 /target/etc/sudoers.d/vagrant

It solves the "no such file or directory" reported by pointing to the right place: /target/etc/

RAAD
  • 31
  • 5
0

echo will work from within an in-target directive. You have to put it with back-ticks (`). For example, I wanted to update the host name of my machine from the preseed file:

in-target hostname echo "ubn"$(lshw | grep -m 1 serial | awk '{print tolower ($2)}')

Back-ticks tells the shell to run this as one command.

0

The original attempt using tee would also work, if you just moved the in-target command to the right place...

d-i preseed/late_command string \
in-target mkdir -v -p -m 0440 "/etc/sudoers.d"; \
echo "%vagrant ALL=(ALL) NOPASSWD: ALL" | in-target tee -a /etc/sudoers.d/vagrant; \
echo "Defaults:vagrant !requiretty" | in-target tee -a /etc/sudoers.d/vagrant; \
in-target chmod 440 /etc/sudoers.d/vagrant;