I am trying to create a bash script that backup the whole /dev/sda1 to /mnt/Backup
/dev/sda1 457G 3.5G 431G 1% /
/dev/sdb1 2.8T 3.0G 2.8T 1% /mnt/Backup
The script that have is :
START=$(date +%D)
FOLDER_NAME=`echo $START | tr -s '/' | tr '/' '_'`
SOURCE_PATH='/media /bin /boot /cdrom /dev /etc /home /lib /opt /proc /root /run /sbin /selinux /srv /sys /tmp /usr /var'
SOURCE_PATH='/'
FOLDER_PATH='/mnt/Backup'
BACKUP_PATH=$FOLDER_PATH/Bkp_$FOLDER_NAME
mkdir -p '$BACKUP_PATH'
cp -r $SOURCE_PATH $BACKUP_PATH
As you can see above on the source path i have tried naming all the folders i wanted to back up but when i run with that path i get an error : this is not a directory
Then i tried the source path "/" below and the copy start but get stucked on
cp: reading `/proc/sysrq-trigger': Input/output error
cp: failed to extend `/mnt/Backup/Bkp_09_14_13/proc/sysrq-trigger': Input/output error
The question is how can i change my script to successfully backup the sda1 to sdb1
Thanks in advance for your help
If /dev/sda1 is mounted as your root filesystem, doing a recursive copy on it would also include the mounted filesystems under its directories. You can mount it again on another directory e.g. /mnt/system then do a recursive copy from it. I suggest using cp -a and not just -r as well.
I'm not sure about your actual program, but here are some little things:
START=$(date +%D)
FOLDER_NAME=`echo $START | tr -s '/' | tr '/' '_'`
Both $() and ` ` do exactly the same. Why would you use both in one script? Prefer $() over backticks because they can be nested. Also, what is the point of tr -s '/' ? First of all, it can be condensed to one tr:
echo "$START" | tr -s '/' '_'
But considering that date +%D will never return repeated slashes you can use pure bash parameter expansion:
FOLDER_NAME=${START//\//_}
How could this even work: mkdir -p '$BACKUP_PATH' ? Variables in single quotes are not expanded. Change to mkdir -p "$BACKUP_PATH"
$SOURCE_PATH does not need quotes in cp -r $SOURCE_PATH $BACKUP_PATH, because you want it to be split into different parameters. That is right. But you have to $BACKUP_PATH because you want it to be a single parameter.
So, here is your script with small improvements:
START=$(date +%D)
FOLDER_NAME=${START//\//_}
SOURCE_PATH='/media /bin /boot /cdrom /dev /etc /home /lib /opt /proc /root /run /sbin /selinux /srv /sys /tmp /usr /var'
SOURCE_PATH='/'
FOLDER_PATH='/mnt/Backup'
BACKUP_PATH=$FOLDER_PATH/Bkp_$FOLDER_NAME
mkdir -p "$BACKUP_PATH"
cp -r $SOURCE_PATH "$BACKUP_PATH"
Related
I am trying to rewrite a bash script to not use the mount command. I want to remove the mount command so I can run this using Windows Subsystem for Linux which currently does not support mounting.
This script is called after compiling some C code into a file called bootimg.
It takes a file mp3.img (a raw binary file), and somehow puts the new bootimg file as well as a filesys_img file into it, producing an updated mp3.img file.
Here is the original code.
#!/bin/sh
if [ -d /mnt/tmpmp3 ]; then
rmdir /mnt/tmpmp3
fi
if [ -d /tmp/mp3 ]; then
rm -rf /tmp/mp3
fi
mkdir /mnt/tmpmp3
mkdir /tmp/mp3
cp ./bootimg /tmp/mp3/
cp ./filesys_img /tmp/mp3/
cp ./mp3.img /tmp/mp3/
mount -o loop,offset=32256 /tmp/mp3/mp3.img /mnt/tmpmp3
cp -f /tmp/mp3/bootimg /mnt/tmpmp3/
cp -f /tmp/mp3/filesys_img /mnt/tmpmp3/
umount /mnt/tmpmp3
cp -f /tmp/mp3/mp3.img ./
rm -rf /tmp/mp3
rmdir /mnt/tmpmp3
I do not really understand how mounting the img file as a loopback device works.
I have been trying to replace mount with dd but have not yet succeeded.
How can I change this scipt to build the updated mp3.img file using dd (or something similar) instead of mounting it?
My guest vm running os freebsd 8.1 and today my /usr is full, and how to increase the /usr from another virtual disk.
ran df command
Filesystem 1K-blocks Used Avail Capacity Mounted on
/dev/da0s1a 1012974 175918 756020 19% /
devfs 1 1 0 100% /dev
/dev/da0s1e 2026030 127744 1736204 7% /tmp
/dev/da0s1f 25384812 23038656 315372 99% /usr
/dev/da0s1d 20308398 10831484 7852244 58% /var
Thanks in advance.
You must get informations about usr partition:
du -s /usr/* | sort -n
For example, you have another partition /usr2 and big subdirectory /usr/local (very big on my system)
And you may (very ugly way):
move /usr/local subdirectory on /usr2 and link it: tar -C /usr -cf - local | tar -C /usr2 -xf - && mv /usr/local /usr/local2 && ln -s /usr2/local /usr && rm -rf /usr/local2
copy all data from usr to usr2 (tar -C /usr -cf - . | tar -C /usr2 -xf -) and change mountpoint on /etc/fstab
If you do not have a big place, you may use first method for subsubdirectory.
For your situation you may:
create subdir in var: mkdir /var/usr/
and use above method with /var/usr instead of /usr2
For example, I want to copy the "file-to-be-copied.txt" from different directories
/home/user1/file-to-be-copied.txt
/home/user2/file-to-be-copied.txt
/home/user3/file-to-be-copied.txt
Then create a new directory based on the user account
/home/user4/user1/
/home/user4/user2/
/home/user4/user3/
Then copy the "file-to-be-copied.txt" to the new created directories
/home/user4/user1/file-to-be-copied.txt
/home/user4/user2/file-to-be-copied.txt
/home/user4/user3/file-to-be-copied.txt
All I know is that it should be done using bash scripting but I don't know how. This is as far as I go
find /home . "file-to-be-copied.txt" | xargs -i mkdir ... cp {} ...
No find necessary, and more so: no xargs (which is almost always superfluous with find, since find has -exec).
cd /home
cp --parents user?/file-to-be-copied.txt user4
for f in $(/usr/bin/find '/home' -name 'file-to-be-copied.txt'); do
tmpname=${f%/*}
dirname=${tmpname##*/}
/bin/mkdir -p $dirname && /bin/cp -p $f $dirname
done
This is the code I used.
for f in $(find '/home' -name 'file-to-be-copied.txt')
do
tmpname=${f%/*}
dirname=${tmpname##*/}
mkdir -p /home/user4/$dirname && /bin/cp -p $f /home/user4/$dirname
echo $f copied to /home/user4/$dirname
done
How do you exclude a folder when performing file operations i.e. cp etc.
I would currently use the wild card * to apply file operation to all, but I need to exclude one single folder.
The command I'm actually wanting to use is chown to change the owner of all the files in a directory but I need to exclude one sub directory.
If you're using bash and enable extglob via shopt -s extglob then you can use !(<pattern>) to exclude the given pattern.
find dir_to_start -name dir_to_exclude -prune -o -print0 | xargs -0 chown owner
find dir_to_start -not -name "file_to_exclude" -print0 | xargs -0 chown owner
for file in *; do
if [ $file != "file_I_dont_want_to_chown" ]
then
chown -R Camsoft $file
fi
done
Combine multiple small sharp tools of unix:
To exclude the folder "foo"
% ls -d * | grep -v foo | xargs -d "\n" chown -R Camsoft
For this situation I would recommend using find. You can specify paths to exclude using the -not -iwhilename 'PATH'. Then using exec you execute the command you want to execute
find . -not -iwholename './var/foo*' -exec chown www-data '{}' \;
Although this probably does help for your situation I have also see scripts set the immutable flag. Make sure you remove the flag when your done you should use trap for this just in case the script is killed early (note: run from a script, the trap code runs when the bash session exits). A lot of trouble in my option but it's good in some situations.
cd /var
trap 'chattr -R -i foo > /dev/null 2>&1' 0
chattr -R +i foo
chown -R www-data *
Another option might be to temporarily remove permission on the that file /folder.
In Unix you need 'x' permission on a directory to enter it.
edit: obviously this isn't goign to work if you are backing up a live production database - but for excluding your 'interesting images' collection when copying documents to a USB key it's reasoanable.
This question already has answers here:
Linux: copy and create destination dir if it does not exist
(27 answers)
Closed 7 years ago.
When copying a file using cp to a folder that may or may not exist, how do I get cp to create the folder if necessary? Here is what I have tried:
[root#file nutch-0.9]# cp -f urls-resume /nosuchdirectory/hi.txt
cp: cannot create regular file `/nosuchdirectory/hi.txt': No such file or directory
To expand upon Christian's answer, the only reliable way to do this would be to combine mkdir and cp:
mkdir -p /foo/bar && cp myfile "$_"
As an aside, when you only need to create a single directory in an existing hierarchy, rsync can do it in one operation. I'm quite a fan of rsync as a much more versatile cp replacement, in fact:
rsync -a myfile /foo/bar/ # works if /foo exists but /foo/bar doesn't. bar is created.
I didn't know you could do that with cp.
You can do it with mkdir ..
mkdir -p /var/path/to/your/dir
EDIT
See lhunath's answer for incorporating cp.
One can also use the command find:
find ./ -depth -print | cpio -pvd newdirpathname
mkdir -p `dirname /nosuchdirectory/hi.txt` && cp -r urls-resume /nosuchdirectory/hi.txt
There is no such option. What you can do is to run mkdir -p before copying the file
I made a very cool script you can use to copy files in locations that doesn't exist
#!/bin/bash
if [ ! -d "$2" ]; then
mkdir -p "$2"
fi
cp -R "$1" "$2"
Now just save it, give it permissions and run it using
./cp-improved SOURCE DEST
I put -R option but it's just a draft, I know it can be and you will improve it in many ways. Hope it helps you
rsync is work!
#file:
rsync -aqz _vimrc ~/.vimrc
#directory:
rsync -aqz _vim/ ~/.vim
cp -Rvn /source/path/* /destination/path/
cp: /destination/path/any.zip: No such file or directory
It will create no existing paths in destination, if path have a source file inside.
This dont create empty directories.
A moment ago i've seen xxxxxxxx: No such file or directory, because i run out of free space. without error message.
with ditto:
ditto -V /source/path/* /destination/path
ditto: /destination/path/any.zip: No space left on device
once freed space cp -Rvn /source/path/* /destination/path/ works as expected