2

I have a shell script (arch-chroot from the Arch Linux arch-install-scripts package) that handles the mounting and unmounting of devices (with error checking) prior to starting a chroot. It starts the chroot on the final line with:

SHELL=/bin/sh unshare --fork --pid chroot "$chrootdir" "$@"

For my use case, I would like to use the exact same script with a "patch" to the final line

SHELL=/bin/bash chroot "$chrootdir" "$@"

What is the best way to do this? If it matters, the arch-chroot script needs to be run with root privileges. Right now I just have a patched copy of the script. If the original script gets updated, then my patched version will be "out of date". I was thinking I could do the copy and patch as needed in a temporary location, but I am not sure if that is better.

Is there a way to temporarily patch a script inplace?

The original script will only be changed when the package it belongs to is updated. My goal is to keep the original script unchanged but have a way of calling a patched version of the most recent version of the original script.

StrongBad
  • 5,261
  • I'm not sure exactly what you're asking. Are you asking how to use the patch utility, or are you asking how to make sure your patch is applied every time the package is updated? – depquid Jan 28 '16 at 18:55
  • @depquid does that help? – StrongBad Jan 28 '16 at 19:02
  • 1
    When I've run into that situation, I've patched the distribution's package. With Debian it is easy, but I don't know how easy it is with Arch. Also, I add a string to the distribution's version number, so apt will still update if there is a newer version, in which case, I need to build a patched package again. – Faheem Mitha Jan 28 '16 at 19:29
  • @StrongBad Sort of. It's still unclear to me whether you know how to use patch and need strategic help or don't know how to use patch and need syntactic help. – depquid Jan 28 '16 at 19:36
  • @depquid I need strategic help. I am comfortable making the change I need with either patch/sed, I just don't know "when" I should apply the patch and if I need a temporary/permanent file. – StrongBad Jan 28 '16 at 19:39

3 Answers3

4

A simple and crude workaround would be to write a little script that creates a temp file with the modified copy of the original arch-chroot and then runs the tmpfile. For example:

#!/bin/sh
scriptfile=$(mktemp /tmp/tempscript.XXXXX)
sed 's#SHELL=.*#SHELL=/bin/bash chroot "$chrootdir" "$@"#' /usr/bin/arch-chroot > $scriptfile

$scriptfile "$@"

Note that this assumes that there is only one line matching the string SHELL= in /usr/bin/arch-chroot and will fail silently if there are more or none.

terdon
  • 242,166
  • A more proper way (less likely to match the wrong line) would be to create a diff and use patch. – depquid Jan 28 '16 at 19:24
  • @depquid absolutely. This is ugly, fragile and prone to error. I've just never used patch myself so I can't write an answer with it. It would be great if you could do so. – terdon Jan 28 '16 at 19:37
  • @depquid I do not think patch is the right tool here. I believe patch will fail if the line I am attempting to "patch", or any of the surrounding lines, change. With sed failures are limited to multiple matches of the "pattern" or a change in the line I am matching such that it no longer matches. – StrongBad Jan 28 '16 at 19:49
  • @StrongBad it might be a good idea to look for the last line of text in the original script instead of the SHELL= pattern. It is probably a safer bet that no matter what changes, the actual chroot command will be the last line of the script. – terdon Jan 28 '16 at 19:51
  • @StrongBad patch's strictness is high customizable. sed is designed for matching data in text files; patch is designed for modifying code. Either will work, but how much risk are you willing to take that the match is wrong? E.g., if the variable name is changed to $chroot_dir, sed will match but then make the code invalid, but patch will return an error. Other breaking changes could be made to the script that neither utility catches; there are no guarantees with automated patching. But in general, patch is more likely to get it right or let you know if there's a problem. – depquid Jan 28 '16 at 20:31
1

if the script you are using is provided in the OS distribution, chances of it getting updated is very high. I would suggest, you write a wrapper script around this original one, which will cut out the original script's last line and appends your customized line to the end. Then calls the newly created copy. It is the simplest way in my opinion.

mv original_script original_script.orig  # make a backup copy of original
sed -i '$ d' original_script.orig > original_script  # remove last line
echo 'SHELL=/bin/bash chroot "$chrootdir" "$@"' >> original_script # add your line to the end
original_script # run the script
mv original_script.orig original_script  #restore the original in place
MelBurslan
  • 6,966
  • 1
    Overwriting the original, even temporally, seems like a bad idea. – StrongBad Jan 28 '16 at 19:24
  • This is a good approach overall, but assuming that the line to be changed is the last one is probably a false assumption and could cause bad things to happen with future versions of the script. – depquid Jan 28 '16 at 19:26
  • @StrongBad yes it is a bad idea but taking precausitons by making a backup copy alleviates it a little. – MelBurslan Jan 28 '16 at 19:50
  • @depquid That assumption is made from original poster's comment, but there always is a possibility of hunting this line down and replacing with what the user wants, using some sed magic – MelBurslan Jan 28 '16 at 19:52
1

Create your own, modified package for this. Take care to keep it up to date, and perhaps use some distribution-specific hack to avoid updating it automatically.

I don't understand the reason for the change you propose (no Arch knowledge whatsoever), but at first glance it is either something you should not do for security reasons, or perhaps your use case is relevant enough to warrant an upstream patch to enable this somehow. In either case, I'd suggest you talk it over with knowledgeable people, via the bug reporting/enhancement request system for your distribution.

Or discuss here what you want to accomplish (not how you are trying to go there, as this question does).

vonbrand
  • 18,253
  • Arch provides a nice wrapper around chroot which automatically mounts a number of useful directories and creates the chroot with its own pid namespace. Both are generally useful things, but in my use case, I only want the directories to be mounted since the program I am trying to run in the chroot does not handle the separate pid namespace correctly.. – StrongBad Jan 28 '16 at 21:03
  • @StrongBad, isn't the separate PID namespace essentially invisible for the processes inside? You should investigate further why it fails. – vonbrand Jan 28 '16 at 21:30
  • I looked into it a little: http://unix.stackexchange.com/questions/235941/pid-in-arch-chroot-is-incorrect – StrongBad Jan 28 '16 at 21:36