Restore bash script - linux

I have a backup directory with a tar file in that directory (/home/username/userhome/backup/userbackup-${currentdate}.tar.gz).
I would like a create a script that:
creates the restore directory if it does not exist
displays the contents of the backup directory containing tar files of previous backups
asks the user to enter the name of the tar file to restore
uses the tar command to restore the file to the new restore directory and log file
So far my script has
#!/bin/bash
mkdir restore -p
ls /home/username/userhome/backup
echo "Enter the file name to be restored"
read $filename
tar xvf "/home/username/userhome/restore/$filename" &>/home/username/userhome/restore/restore.log
I am a complete newbie so any help will be greatly appreciated.

Continuing from the comment, one thing you always want to do when writing a script is to validate each step along the way. For instance, if you cannot create the new restore directory, you don't want to loop and then attempt to extract a tar.gz file to the directory that doesn't exits.
Virtually all commands return 0 on success or a nonzero error on failure. You can use this to your advantage to check if the command succeeded and if it didn't you simply exit. A quick way to do that is:
command || exit 1
In your case creating the restore directory that could be:
mkdir -p restore || exit 1
You can add additional error messages if you like, but most time the error generated by the failure will be sufficient to tell you what went wrong.
Whenever you are operating on a fixed base directory using subdirectories of that base, it is best to create a variable for that base directory you can use in your script. For example:
#!/bin/bash
userdir="${1:-/home/username/userhome}"
budir="$userdir"/backup
restore="$userdir"/restore
Here userdir is the base directory and you have additional variables for the backup directory and restore directory. This makes it convenient to reference or operate on files in any of the directories. Note also how userdir can be set from the first command line argument or uses /home/username/userhome by default if no argument is given.
You can create restore and change to that directory, validating each step as follows:
mkdir -p restore || exit 1
cd "$restore" || exit 1
For the menu, let select create the menu for you (now if you have hundreds of .tar.gz files, you may need to write a custom pager, but for a few dozen files, select will be fine). You can generate the menu and restore the selected file with:
select choice in "$budir"/*.tar.gz; do
tar -xvf "$choice" &>"$restore/restore.log"
break
done
Putting it altogether, you would have:
#!/bin/bash
userdir="${1:-/home/username/userhome}"
budir="$userdir"/backup
restore="$userdir"/restore
mkdir -p restore || exit 1
cd "$restore" || exit 1
select choice in "$budir"/*.tar.gz; do
tar -xvf "$choice" &>"$restore/restore.log"
break
done
Example Use/Output
Say I have a couple of .tar.gz files in a directory, e.g.
$ tree /home/david/tmpd/backup
backup
├── v.tar.gz
└── x.tar.gz
Then to create a restore directory under the tmpd directory I can run the script as:
$ bash ~/scr/tmp/restore.sh /home/david/tmpd
1) /home/david/tmpd/backup/v.tar.gz
2) /home/david/tmpd/backup/x.tar.gz
#? 2
By choosing 2 above the x.tar.gz file is restored under the restore directory, e.g.
$ ls -al restore/
total 4
drwxr-xr-x 3 david david 80 Oct 29 01:00 .
drwxr-xr-x 4 david david 80 Oct 29 01:00 ..
drwxr-xr-x 3 david david 60 Oct 29 01:00 home
-rw-r--r-- 1 david david 57 Oct 29 01:00 restore.log
So the restore directory was successfully created, the restore.log was created and the .tar.gz file was restored under the restore directory.
The contents of restore.log are
$ cat restore/restore.log
home/david/scr/utl/xscrd.sh
home/david/scr/utl/xzdate.sh
(which were the two sample files I added to the x.tar.gz file)
Look things over and let me know if you have further questions.

Related

Permission with tar command

I have some problem with linux "tar" command.I want to unzip a config001.gz to a directory(with owner root ,group root and 777 permission as show in pic).
My origin dir and target dir is shown in pic.
My question is:
why there is en empty folder in a config001.gz file(I try to tar two file together and look in the the config002.tgz file ,there is no empty dir)?
if I don't append --no-overwrite-dir after command,it will raise error, what permission does "tar" want to change?
why --no-overwrite-dir option can fix the problem
my mount infomation:
fuse.mfs rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other 0 0
why there is en empty folder in a config001.tgz file?
There is the "root folder" included in the tar archive. The folder the tar was in. The privileges, owner and group, permissions and creation/modification (or one of them, I am not sure) dates are included. You can create such archive with:
mkdir -p /tmp/a
cd /tmp/a
echo 123 > 1
echo 234 > 2
tar cfvp /tmp/test.tar .
# and inspect with:
tar -tvf ./test.tar
drwxr-xr-x kamil/kamil 0 2019-07-15 12:50 ./
-rw-r--r-- kamil/kamil 4 2019-07-15 12:50 ./2
-rw-r--r-- kamil/kamil 4 2019-07-15 12:50 ./1
By specifing the ., ie. the current directory, the information about the current directory itself will be included in he tar. Ie. the information about the owner and group, permissions and dates.
if I don't append --no-overwrite-dir after command,it will raise error, what permission does "tar" want to change?
tar wants to change the permissions of the directory you are inside. The hpc_dir directory. The hpc_dir is owned by root, so tar can't change/touch it.
why --no-overwrite-dir option can fix the problem?
Because then tar sees the the currect directory hpc_dir exists. Because of that, tar doesn't try to create the directory, nor tries to change the owner and group permissions of the directory, nor tries to restore the creation date of the directory.
You could just go with mkdir somedir; tar xzfv archive.tar -C somedir - that way the somedir will be created by current user, so tar will be able to change it's properties.
Or you could just change the owner of hpc_dir directory, letting your user modify it.

symlink installed java to /usr/java/latest

A program requires a java directory location of /usr/java/latest. In many cases this directory does not exist. In order to get the program to run correctly I need to do the following steps:
mkdir -p /usr/java
mkdir -p /usr/java/latest
Then I need to find what java installations are available and symlink them to the above directories:
ll /usr/lib/jvm
I usually choose the latest directory avialable...ie:
drwxr-xr-x. 3 root root 16 Feb 12 2016 java-1.8.0-openjdk-1.8.0.71-2.b15.el7_2.x86_64
and then create a link to /usr/java/latest
ln -s /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.71-2.b15.el7_2.x86_64/jre/lib /usr/java/latest/lib
ln -s /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.71-2.b15.el7_2.x86_64/jre/bin /usr/java/latest/bin
I am trying to create an installation script that automates the above process without having to copy and paste the directory name for the symbolic link. Basically I want to parse the /usr/lib/jvm/ directory for the most recent (or any) available java directory. Then I want to take that and link the lib and bin directories within that directory to the /usr/java/latest directory. Thank you in advance for any type of advice.
I am using the below to find the directory I need.
ls -F /usr/lib/jvm | grep / | sed '$!d' | sed 's:/*$::'

check if user can access /root directory before running command

I have a homework assignment that asks me to print certain things in a linux terminal with bash scripting. I have done most of them but I am stuck on the last thing I need to do...This is how my professor worded it
Checks to see if current user has access to /root
-lists files in the root directory if so
-Hint: try using 'ls'
Any help will be appreciated.
Conditional Expressions and Symbolic Permissions
The simplest solution is to use a Bash conditional expression to check directory read permissions. For example:
[[ -r /root ]] && ls /root
If you'd rather inspect the permissions visually, you can use ls to list the directory (rather than its contents) with the -d flag. For example:
$ ls -lad /root
drwxr-x--- 6 root wheel 204 Oct 25 04:45 /root
You can then parse the permissions using symbolic notation to see if the current user would have access to its contents, but doing it that way just seems like the long way around when you can just use a conditional or handle the exit status of ls directly:
ls /root || echo "Grade: 'F' for effort." > /dev/stderr

Can't write on hard drive owned by user and with permissions to write, read and execute

I am very puzzled by this problem I am having. I am trying to execute a file in Ubuntu 12.04 LTS via command line. I have a script that calls a program to run and write the results in a hard drive. I changed the permissions and ownership of everything to be wxr. Here is the ls -l of my script (called TEST-star):
-rwxrwxrwx 1 root root 950 Nov 15 13:16 TEST-star
Here is the ls -l of the package my script calls:
-rwxrwxrwx 1 root root 1931414 Nov 10 12:37 STAR
Finally the ls -l of the hard drive mounted in /media/CLC"
drwxrwxrwx 1 root root 8192 Nov 15 13:04 CLC
I have been trying to run it since yesterday and always get a message that I don't have permission to write the results:
EXITING because of FATAL ERROR: could not create output file ./_STARtmp//Unmapped.out.mate1.thread14
Solution: check that you have permission to write this file
I thought if I change the permissions to rwx and run my script as root it would not have a problem (using sudo). Right now I run out of options. Any suggestion would be appreciated. Please let me know what other information you would need solve this issue.
Thank you.
Here is the first line of script I am trying to run:
#!/bin/sh
cd /media/CLC/ANOPHELES-STAR-v2.4f1/; mkdir GambFemAnt1 && cd GambFemAnt1; echo $PWD && echo Starting mapping of GambFemAnt1; /home/aedes/Documents/STAR_2.4.0f1/STAR --genomeDir /media/Galaxy/Galaxy_data/Anopheles/STAR/Genome --readFilesIn /media/Galaxy/Galaxy_data/Anopheles/QC/GambFemAnt1/GambFemAnt1.fastq --runThreadN 23 --outFilterMismatchNmax 4 --outFilterMatchNminOverLread 0.75 --seedSearchLmax 30 --seedSearchStartLmax 30 --seedPerReadNmax 100000 --seedPerWindowNmax 100 --alignTranscriptsPerReadNmax 100000 --alignTranscriptsPerWindowNmax 10000 --outSAMstrandField intronMotif --outFilterIntronMotifs RemoveNoncanonical --outSAMtype BAM SortedByCoordinate --outReadsUnmapped Fastx; mv Aligned.sortedByCoord.out.bam GambFemAnt1.bam; mv Unmapped.out.mate1 GambFemAnt1-unmapped.fastq; cp *.fastq /media/CLC/ANOPHELES-STAR-v2.4f1/UNMAPED-reads/; cd /media/CLC/ANOPHELES-STAR-v2.4f1 && echo $PWD && echo GambFemAnt1 mapping finished;
I also posted a question for the authors of the package.
Turns out all the permissions were set correctly. The problem resigns within the package. I found out that it works using --runThreadN 12 instead of --runThreadN 23.

Linux: 'transferring'/mirroring read-only permissions for symlinks (for webserver)

Please let me explain what I mean by the question:
This is the context: I'm a user on a webserver, where I have phpicalendar installed; then, I choose a directory, say /webroot/mylogin/phpicalendar/mycals to host my .ics calendar text files.
EDIT: Previously, instead of '/webroot', I had used '/root' - but I really didn't mean the Linux '/root' directory - I'm just wanted to use it as a stand in for the real location on the webserver (so it serves just as a common point of reference). Otherwise, what I mean by common point of reference, is simply /webroot = /media/some/path ..
Then, I can enter this directory in the phpicalendar's config.inc.php:
$configs = array(
'calendar_path' => '/webroot/mylogin/phpicalendar/mycals;
...
Then, phpicalendar will run through this directory, grab the .ics files there (say, mycal.ics and mycal2.ics) and render them - so far, so good.
The thing is, I would now like to add a second calendar directory, located at the same webserver, but where I have read-only permissions, say /webroot/protected/cals. I know that I have read permissions, because I can do in the shell, say
$ less /webroot/protected/cals/maincal.ics
and I can read the contents fine.. So now:
If I enter /webroot/protected/cals as a 'calendar_path', phpicalendar can read and render the files there (say, 'maincal.ics', 'maincal2.ics') without a problem
However, phpicalendar can have only one 'calendar_path', so I can either use the protected calendars, or my customized calendars - but not both
So, I thought, I could symlink the protected calendars in my customized directory - and get the best of both worlds :)
So, here is a shell snippet of what I would do
$ cd /webroot/mylogin/phpicalendar/mycals
$ ls -la
drwxrwxrwx 2 myself myself 4096 2011-03-03 12:50 .
-rw-r--r-- 1 myself myself 1234 2011-01-20 07:32 mycal.ics
-rw-r--r-- 1 myself myself 1234 2011-01-20 07:32 mycal2.ics
...
$ ln /webroot/protected/cals/maincal.ics . # try a hard link first
ln: creating hard link `./maincal.ics' => `/webroot/protected/cals/maincal.ics': Invalid cross-device link'
$ ln -s /webroot/protected/cals/maincal.ics . # symlink - works
$ ln -s ../../../protected/cals/maincal.ics relmaincal.ics # symlink via relative
$ ln -s mycal.ics testcal.ics # try a symlink to a local file
$ ls -la # check contents of dir now
drwxrwxrwx 2 myself myself 4096 .
-rw-r--r-- 1 myself myself 1234 mycal.ics
-rw-r--r-- 1 myself myself 1234 mycal2.ics
lrwxrwxrwx 1 myself myself 21 testcal.ics -> mycal.ics
lrwxrwxrwx 1 myself myself 56 maincal.ics -> /webroot/protected/cals/maincal.ics
lrwxrwxrwx 1 myself myself 66 relmaincal.ics -> ../../../protected/cals/maincal.ics
Ok, so here's what happens:
less maincal.ics works on shell
less relmaincal.ics fails with 'relmaincal.ics: No such file or directory' (even if shell autocompletion for the relative path did work during the execution of the symlink command!)
When you open phpicalendar now, it will render mycal.ics, mycal2.ics and testcal.ics (and they will work)
however, maincal.ics and relmaincal.ics will not be parsed or displayed
Now - this could be that PHP cannot resolve symlinks; however I speculate that the situation is this:
When I do less maincal.ics - it is myself who is user, who has read permission for /webroot/protected/cals
phpicalendar (so Apache webserver user) can otherwise also access /webroot/protected/cals as read-only, when given 'hardcoded' path
phpicalendar is also capable of reading local symlinks fine
Thus, I suspect, that the problem is: when trying to read the symlinks to protected cals, the user that is visible to the shell during that operation is Apache web user, which then doesn't get permissions to access a symlink to the protected/cals location!
The thing now is - I can easily copy the .ics files locally; however they are being changed by someone else, which is why I'd have preferred a symlink.
And my question is: can I do some sort of trickery, so that when phpicalendar/Apache tries to access a symlink to protected/cals, it 'thinks' that it is a local file - and otherwise, the contents of the protected/cals file are being 'piped' back to phpicalendar/Apache?? I guess I'm thinking something in terms of:
$ mkfifo mypipe
$ ln -s mypipe testpipe.ics
$ cat ./testpipe.ics # in one terminal
$ cat /webroot/protected/cals/maincal.ics > mypipe # in other terminal
... which would otherwise (I think) handle the permissions problem - except that, I don't want to cat manually; that would be something that would have to be done in the background, each time an application requests to read testpipe.ics:)
Well, thanks in advance for any comments on this - looking forward to hearing some,
Cheers!
Umm, I really doubt that the account the web server runs under can read anything under /root. That directory is usually mode 0700, user root, group root, or something very similar to that - meaning no non-root access is allowed. If you're running the web server as root, file read permissions are the least of your problems...
Your best bet then would be to place the read-only calendar files somewhere publicly available, and symlink to that location from wherever under /root you want to be able to access them.
Start by checking whether the Apache user can view your calendars:
you#host $ sudo -i -u <apache-user> -s /bin/bash
apache#host $ less /root/protected/cals/maincal.ics

Resources