Page 1 of 1

Selective changes

Posted: 24 Mar 2014, 06:07
by Kriss
Edit 2014-03-30: Changed

Code: Select all

for i in $(find /changes -type f | sed 's/\/changes//'); do
to

Code: Select all

find /changes -type f | sed 's/\/changes//' |while read i; do
To e able to use filenames with spaces.
Hello!
Recently I've lost my usb flash so right now I'm trying to rebuild what I had there, and this topic is about one of preferred scripts.
Idea with "changes.dat" file is nice, but I had several occasions where it resulted in corrupted files (it was long ago and I didn't use it since then), so for a long time I used Porteus where I manually set up the way I want using rootcopy folder.
It gave me more control over the scope of files that I wanted to allow to change
But recently I've decided to write a couple of scripts to automatically change certain files.
Basically I've created directory "./rootcopy/changes" where I placed files that I wanted to allow changes to.
On boot, they are copied to "/" along with everything else inside "rootcopy".
Then a simple script in rc.local:

Code: Select all

echo Removing destination files and linking:
find /changes -type f | sed 's/\/changes//' |while read i; do
echo "/changes$i" '>>' "$i"
rm -f "$i"
mkdir -p $(echo $i | sed 's/\/[^\/]*$//')
ln -s "/changes$i" "$i"
done
deleted destination files (if they exist inside /changes)
created directories as needed for new files (not files actually, just links to /changes/dir1/dir2/file)
and symlinking files inside /changes where they should be.

And on shutdown I used something like this in rc.local_shutdown:

Code: Select all

CHPATH=$(grep "/rootcopy" /var/log/porteus-livedbg | tail -n +2 | sed 's/UUID[^\/]*//')
UUID=$(grep "/rootcopy" /var/log/porteus-livedbg | tail -n +2 | sed -re 's/\/.+//' | sed 's/UUID://')
echo "$UUID"

if [ ! $UUID = '' ]; then
  CHDISK=$(find /dev/disk/by-uuid/$UUID -type l -print0 | xargs -0 ls -plah | sed -re 's/^.+\///')
fi

if ! mount -l | grep $CHDISK > /dev/null ; then
  mkdir -p /mnt/$CHDISK
  mount -t auto /dev/$CHDISK /mnt/$CHDISK
fi
echo /mnt/$CHDISK$CHPATH/changes
cp -u -r /changes /mnt/$CHDISK$CHPATH
It has one disadvantage though, only files are being used for symlinks but not the whole folders. Probably I'll patch up something exclusively for directories later.

Anyway, just wanted to share this with everybody in case someone wants similar setup.
These scripts aren't elegant (I didn't have much time to re-create them after the loss of data), but at least they work for me. Most likely someone knows better ways to do this kind of thing.
Of course I had many other personal scripts (like the one that links all drives to ~/disks, all "games*", "music*", etc from all disks into appropriate folders inside home folder ) but I doubt the will be of much use... I think...

Re: Selective changes

Posted: 24 Mar 2014, 17:09
by tome
Most likely someone knows better ways to do this kind of thing.
I use similar way for it (less scripts), will share when enough ready.

Re: Selective changes

Posted: 25 Mar 2014, 04:13
by Kriss
That would be interesting... =)

P.S. I was thinking about using cron or something else to automatically search Porteus usb, mount it (if it wasn't mounted), write changes and unmount (if it wasn't mounted already), but I don't have much time. Someday... =)

Re: Selective changes

Posted: 03 Apr 2014, 02:48
by Kriss
At the moment it looks like this:
/usr/bin/changes

Code: Select all

#!/bin/sh

function linkfiles {
  echo Removing destination files and linking:
  echo "Source dir: $1"
  find "/$1" -type f | sed "s/\/$1//" |while read i; do
    echo "file:$i"
    rm -f "$i"
    mkdir -p $(echo $i | sed 's/\/[^\/]*$//')
    ln -s "/$1$i" "$i"
  done
}

function linkdirs {
find "/$1" -type d -name "*.linkdir" | sed -e "s/\/$1//" -e 's/.linkdir//' |while read i; do
  echo "dir:$i"
  rm -Rf "$i"
  rm -Rf "$i.linkdir"
  mkdir -p $(echo $i | sed 's/\/[^\/]*$//')
  ln -s "/$1$i.linkdir" "$i"
done
}
function mntdisk {
if [ ! $1 = '' ]; then
  CHDEV=$(readlink /dev/disk/by-uuid/$1 | sed -re 's/^.+\///')
  CHUUID=$(find /dev/disk/by-uuid/$1 -type l | sed -re 's/^.+\///')
  CHLABEL=$(find /dev/disk/by-label/ -type l -print0 | xargs -0 ls -plah | grep `readlink /dev/disk/by-uuid/$1 | sed -re 's/^.+\///'` | sed -re 's/^.+by-label\///' -e 's/ -> .*//')
  CHFORMAT=$CHDEV
  echo format $CHFORMAT
  mkdir /root/disks 2> /dev/null
    if [ "$CHLABEL" = "" ]; then
      echo linking /mnt/$CHDEV to /root/disks/$CHFORMAT
      if ! find /root/disks/$CHFORMAT; then ln -s /mnt/$CHDEV /root/disks/$CHFORMAT;else echo "/root/disks/$CHFORMAT exists, skipping";fi
    else
      CHFORMAT="$CHLABEL ($CHDEV)"
      if ! find "/root/disks/$CHFORMAT"; then ln -s /mnt/$CHDEV "/root/disks/$CHFORMAT";else echo "/root/disks/$CHFORMAT exists, skipping";fi
    fi
    echo $CHLABEL $CHDEV $CHUUID
fi
}

function save {
CHPATH=$(grep "/rootcopy" /var/log/porteus-livedbg | tail -n +2 | sed 's/UUID[^\/]*//')
UUID=$(grep "/rootcopy" /var/log/porteus-livedbg | tail -n +2 | sed -re 's/\/.+//' | sed 's/UUID://')
echo "$UUID"
if [ ! $UUID = '' ]; then
 CHDISK=$(find /dev/disk/by-uuid/$UUID -type l -print0 | xargs -0 ls -plah | sed -re 's/^.+\///')
fi
if ! mount -l | grep $CHDISK > /dev/null ; then
  mkdir -p /mnt/$CHDISK
  mount -t auto /dev/$CHDISK /mnt/$CHDISK
fi
echo /mnt/$CHDISK$CHPATH/$1
cp -u -r -L /$1 /mnt/$CHDISK$CHPATH
}

case "$1" in
'start')
  HOMEDIR=/root
  #mkdir -p $HOMEDIR/disks
  linkfiles changes
  linkdirs changes
  for i in $(find /dev/disk/by-uuid/ -type l | sed -re 's/^.+\///'); do
    mntdisk $i
  done
;;
'stop')
  save changes
;;
*)
echo "Usage: $0 {start|stop}"
;;
esac
This script will link all files inside "/changes" (can be changed to anything else that is located in "/") to their appropriate places inside /. for example "/changes/etc/conky/conky.conf" will be linked to "/etc/conky/conky.conf"
If you'll add ".linkdir" to any directory inside "/changes", then this directory will be linked instead of its content, for example, directory "/changes/root.linkdir" will be linked to "/root".

Oh, and it will create directory "/root/disks" and will link all disks there (using format "label (device)" if possible).

Keep in mind, this script is WIP and I omitted most of the code that caters to my personal needs.
For example I use directories like "games.online", "games.online", "games.steam", "games.somethingelseyoucanthinkof" and I link them all to "/root/games/disk-label.suffix", same for music, videos and other directories that starts with certain word. But I'm not sure it will be useful for anyone else. If I'm wrong, just let me know...

Re: Selective changes

Posted: 03 Apr 2014, 03:32
by brokenman
Nice job. Some nice code there. It gives you precise control.

Did you know about 'magic folders'?

Re: Selective changes

Posted: 03 Apr 2014, 06:40
by Kriss
@brokenman
Thank you!
Yes, I wanted control over what's being stored on my usb flash, since I think that most of the data that's being stored in changes is just a waste of speed and space on usb flash in my opinion (firefox profile directory is an example).
The script I've created is very far from being elegant, but it suits my tastes and I just wanted to show approach that I prefer in case someone want (or better - have) something similar.

I didn't know about magic folders to be honest, but after a bit of reading I got an impression that they require porteus flash to be mounted permanently, and I'd prefer some sort of script that tries to mount disk on exit (before saving changes to disk).
And what about using UUID? Is it possible for magic folders?

I'll read more about it when I got home... Busy day at work, as usual... =)