Shell script.....if error do this instead - shell

At my home I have 2 PCs, my main windows gaming rig, and an ubuntu 13.04 file server. (NOT running ubuntu server just plain ubuntu)
I have the OS drive encrypted with luks (through installation)
But i have 5 Truecrypt ecrypted HDDs. They need to stay truecrypt for my needs. I have the following 2 scripts setup to mount my drives on boot of the PC.
This simple one to open terminal and run the next script-
#!/bin/bash
sleep 10
gnome-terminal -e /home/kun7/.TrueCrypt/mount_truecrypt_volumes.sh
And then the following code runs to get truecrypt password and mount drive to my specified points (needs to goto specified points for my other programs/libraries/shortcuts etc
#!/bin/bash
echo "Enter password ..."
oldConfig=`stty -g`
stty -echo
read password
stty $oldConfig
echo "Opening Pandora's Box ..."
truecrypt -t /dev/sdb5 /media/P --password="$password" -k "" --protect-hidden=no
truecrypt -t /dev/sda1 /media/B --password="$password" -k "" --protect-hidden=no
truecrypt -t /dev/sdd1 /media/M --password="$password" -k "" --protect-hidden=no
truecrypt -t /dev/sde1 /media/V --password="$password" -k "" --protect-hidden=no
truecrypt -t /dev/sdf /media/S --password="$password" -k "" --protect-hidden=no
echo "Drives mounted ... Close when ready"
exit 0
This works great for what I need. On occasion. My problem is that I have 2 drives connected via a PCI card. NORMALLY they are detected by the OS as sdb5 and sda1, but every now and then they get identified as sdc5 and sdd1.
This causes my script return...
Enter password ...
Opening Pandora's Box ...
Enter your user password or administrator password:
Error: No such file or directory:
/dev/sdb5
Incorrect password or not a TrueCrypt volume.
Enter password for /dev/sda1: Error: No such file or directory:
/dev/sdd1
Incorrect password or not a TrueCrypt volume.
Enter password for /dev/sdf:
What I'm wanting to do is to add an "if error" command at the end of my script to tell it. "If error, use this instead" and then list the alternate mount paths when the OS changes the drive points.
I think that makes sense.

I recommend you use the drives UUIDs instead.
You can get the drives UUID with:
$ sudo /sbin/blkid /dev/sda1
> /dev/sda1: UUID=<SOME-UUID-STRING> TYPE=<TYPE>
And with blkid -U <UUID> you query the device path. So in your script use this instead:
truecrypt -t $(/sbin/blkid -U <SOME-UUID-STRING>) /media/...
If you really prefer the "on error" approach:
function mount-truecrypt () {
local dev=$1
local mnt=$2
local alternative_dev=$3
truecrypt -t $dev $mnt --password="$password" -k "" --protect-hidden=no || \
truecrypt -t $alternative_dev $mnt --password="$password" -k "" --protect-hidden=no
}
mount-truecrypt /dev/sdb5 /media/P /dev/sdc5
Update:
Ok, UUIDs don't work because the partition table isn't available before decrypting with truecrypt and the devices are kind of random.
Here some tips for your udev rules: Writing udev rules might help you and this command:
sudo udevadm info -a -p $(sudo udevadm info -q path -n /dev/sda)
(From udevinfo) Gives you all the udev infos on your drives.
Though that's probably not easy either, since the partitions won't be available to udev either ..
But you could figure out where the main block device of you drive is by creating a symlink for the drive with a rule like this:
ATTRS{model}=="<MODEL>", ATTRS{serial}=="<SERIAL>", ACTION=="add", SYMLINK+="<my-symlink>"
Then /dev/ points to the device (/dev/sda or so) with readlink you can follow links like this:
readlink -f /dev/<my-symlink>
So you could try this in your script:
truecrypt "$(readlink -f /dev/<my-symlink>)1" <args>
To mount partition 1 on that drive. I'm not sure if it works, but mighht give you some ideas .

The problem is that for terminal/script mounting of drives through truecrypt your doing this:
truecrypt -t /dev/sda /media/Stuff
But if the /dev/sda change for each physical drive everytime you boot up, then this makes the script worthless. All links, and libraries are setup from /media/stuff which in turn rely on /dev/sda pointing to the same drive each time. So i need to make some persistent /dev/* points for truecrypt to use.
TIP: use udev to fond the info your using for matches, and make sure your setting completely random/customized /dev/*
Here is my current process for getting everything to work
1 - PC boots and takes rules from 10-custom-hdd-scsi.rules
2 - Login to Ubuntu where 1 script open terminal and then runs "3"
3 - Truecrypt script prompts for password, and mounts drives to specified mount points allowing for links/libraries to work.
First run - sudo /lib/udev/scsi_id --page=0x83 --whitelisted --device=/dev/sda and copy the result down. Do it for each drive you have, and you`ll have the Drives scsi id
10-custom-hdd-scsi.rules - This file has been saved in /etc/udev/rules.d
# These are the rules to force all drives into specific /dev/sd** slots for truecrypt mounting
#
#KERNELS - looks upwards in device path to find
#PROGRAM - Runs this. It is a serch for WWID (world wide ID)
#RESULT - This is the result its looking for. It is the specific Drives ID
#SYMLINK - Create the following link (i.e. personal /dev/***)
#
# "==" means match this
# "+=" means if it exists, do this aswell
#
KERNEL=="sd*", PROGRAM=="/lib/udev/scsi_id --page=0x83 --whitelisted --device=/dev/%k", RESULT=="<DRIVES ID>", SYMLINK+="TC-a%n"
KERNEL=="sd*", PROGRAM=="/lib/udev/scsi_id --page=0x83 --whitelisted --device=/dev/%k", RESULT=="<DRIVES ID>", SYMLINK+="TC-b%n"
KERNEL=="sd*", PROGRAM=="/lib/udev/scsi_id --page=0x83 --whitelisted --device=/dev/%k", RESULT=="<DRIVES ID>", SYMLINK+="TC-c%n"
KERNEL=="sd*", PROGRAM=="/lib/udev/scsi_id --page=0x83 --whitelisted --device=/dev/%k", RESULT=="<DRIVES ID>", SYMLINK+="TC-d%n"
KERNEL=="sd*", PROGRAM=="/lib/udev/scsi_id --page=0x83 --whitelisted --device=/dev/%k", RESULT=="<DRIVES ID>", SYMLINK+="TC-e%n"
BANG - custom udev rules to create a link for each drive. so now you`ll have the standard /dev/sd** that change everytime, AND /dev/TC-a that will stay the same.
First script to open terminal
#!/bin/bash
gnome-terminal -e /home/kun7/.TrueCrypt/mount_truecrypt_volumes.sh
And now the script telling truecrypt to mount your drives
#!/bin/bash
echo "Enter password ..."
oldConfig=`stty -g`
stty -echo
read password
stty $oldConfig
echo "Opening Pandora's Box ..."
truecrypt -t /dev/TC-a /media/E --password="$password" -k "" --protect-hidden=no
truecrypt -t /dev/TC-b /media/D --password="$password" -k "" --protect-hidden=no
truecrypt -t /dev/TC-c /media/C --password="$password" -k "" --protect-hidden=no
truecrypt -t /dev/TC-d /media/B --password="$password" -k "" --protect-hidden=no
truecrypt -t /dev/TC-e /media/A --password="$password" -k "" --protect-hidden=no
echo "Drives mounted ... Close when ready"
exit 0
-Now you'll boot up the PC, login, and get a terminal asking you for your truecrypt password.
-Type it in.
-And then you`ll be asked for your user password.
-The script will run, your drives will be mounted.
-And you now have continuous persistent mount point for your drives.

Related

Making an app using ssh to shutdown macbook

I have been trying to create an app that can shutdown my mac using ssh. I've tried ssh-copy-id -i ~/.ssh./id_rsa.pub ssh "my computer" | sudo shutdown -h now but I get an error message saying zsh:exit 1 and zsh: suspended (tty output) sudo shutdown -h now and I don't know what to do.
There are several issues with your command:
ssh-copy-id -i ~/.ssh./id_rsa.pub ssh "my computer" | sudo shutdown -h now
That's two commands. You need a semicolon or line break to separate them
ssh-copy-id needs the private key, but you've provided the public key
That key looks like it has an extra dot in the key path
You're running sudo shutdown -h now locally rather than remotely
Run this just one time. It will prompt you for your user's password on mycomputer:
ssh-copy-id -i ~/.ssh/id_rsa mycomputer
Then you can run this:
ssh -t mycomputer "sudo shutdown -h now"
This will be interactive since you need to enter your user password for sudo, but at least the key prevents you from needing to enter it a second time to gain access to the system.
You could reduce this by allowing your user to run that command without a password. From a shell on that computer (ssh mycomputer), run visudo (if the last line of that file looks like #includedir /etc/sudoers.d, quit and run something like visudo -f /etc/sudoers.d/local) and add this to the end:
gjwlsdnd224 ALL=(root) NOPASSWD: /sbin/shutdown -h now
where gjwlsdnd224 is your username. If you do this, you don't need -t passed to ssh.

Shell script for connecting network drives crashes my MacBook's internet capabilities

My work requires me to connect to several network drives over two different protocols, SMB and SSHFS. I got tired of typing in the commands to connect to them individually and being prompted for my password every time, so I wrote this script:
#!/bin/sh
# SSHFS shares
local_paths=("/Users/$USER/mnt/share_1" "/Users/$USER/mnt/share_2" "/Users/$USER/mnt/share_3")
remote_paths=("$USER#server.university.edu:/home/$USER" "$USER#server.university.edu:/some/path" "$USER#server.university.edu:/another/path")
echo "Enter password:"
read -s password
for i in "${!local_paths[#]}"; do
diskutil unmount ${local_paths[$i]}
echo "Mounting ${remote_paths[$i]} to ${local_paths[$i]}"
mkdir -p ${local_paths[$i]}
sshfs -o password_stdin ${remote_paths[$i]} ${local_paths[$i]} -o volname=$(basename ${local_paths[$i]}) <<< $password
echo
done
# SMB shares
local_paths=("/Users/$USER/mnt/share_4" "/Users/$USER/mnt/share_4")
remote_paths=("//$USER#different.server.university.edu:/home/$USER" "//$USER#different.server.university.edu:/some/path")
for i in "${!local_paths[#]}"; do
diskutil unmount ${local_paths[$i]}
echo "Mounting ${remote_paths[$i]} to ${local_paths[$i]}"
mkdir -p ${local_paths[$i]}
mount_smbfs ${remote_paths[$i]} ${local_paths[$i]}
done
It just loops through every path and disconnects/reconnects. It mostly works. After running it, I gain access to four of the five drives. For some reason, the last SSHFS in the array will mount, but I get a "permission denied" error message when I try to open the folder where it is mounted. If I re-order the array, it is always the last path that will error out like this. I have no such issue with the SMB shares.
Once this error happens, my computer is bugged out. Trying to forcibly unmount the share will just freeze my terminal. I lose all ability to access websites or do anything else that uses a network connection. I can't even restart the computer without holding down the power button for a hard reset.
Technical Specs:
Intel MacBook Pro
MacOS Big Sur
zsh, but I've tried this script in bash and sh with the same result.
Notes:
I tested this on a colleague's laptop and got the same results.

Send command after exec [duplicate]

I know it is not recommended, but is it at all possible to pass the user's password to scp?
I'd like to copy a file via scp as part of a batch job and the receiving server does, of course, need a password and, no, I cannot easily change that to key-based authentication.
Use sshpass:
sshpass -p "password" scp -r user#example.com:/some/remote/path /some/local/path
or so the password does not show in the bash history
sshpass -f "/path/to/passwordfile" scp -r user#example.com:/some/remote/path /some/local/path
The above copies contents of path from the remote host to your local.
Install :
ubuntu/debian
apt install sshpass
centos/fedora
yum install sshpass
mac w/ macports
port install sshpass
mac w/ brew
brew install https://raw.githubusercontent.com/kadwanev/bigboybrew/master/Library/Formula/sshpass.rb
just generate a ssh key like:
ssh-keygen -t rsa -C "your_email#youremail.com"
copy the content of ~/.ssh/id_rsa.pub
and lastly add it to the remote machines ~/.ssh/authorized_keys
make sure remote machine have the permissions 0700 for ~./ssh folder and 0600 for ~/.ssh/authorized_keys
If you are connecting to the server from Windows, the Putty version of scp ("pscp") lets you pass the password with the -pw parameter.
This is mentioned in the documentation here.
curl can be used as a alternative to scp to copy a file and it supports a password on the commandline.
curl --insecure --user username:password -T /path/to/sourcefile sftp://desthost/path/
You can script it with a tool like expect (there are handy bindings too, like Pexpect for Python).
You can use the 'expect' script on unix/terminal
For example create 'test.exp' :
#!/usr/bin/expect
spawn scp /usr/bin/file.txt root#<ServerLocation>:/home
set pass "Your_Password"
expect {
password: {send "$pass\r"; exp_continue}
}
run the script
expect test.exp
I hope that helps.
You may use ssh-copy-id to add ssh key:
$which ssh-copy-id #check whether it exists
If exists:
ssh-copy-id "user#remote-system"
Here is an example of how you do it with expect tool:
sub copyover {
$scp = Expect->spawn("/usr/bin/scp ${srcpath}/$file $who:${destpath}/$file");
$scp->expect(30,"ssword: ") || die "Never got password prompt from $dest:$!\n";
print $scp 'password' . "\n";
$scp->expect(30,"-re",'$\s') || die "Never got prompt from parent system:$!\n";
$scp->soft_close();
return;
}
Nobody mentioned it, but Putty scp (pscp) has a -pw option for password.
Documentation can be found here: https://the.earth.li/~sgtatham/putty/0.67/htmldoc/Chapter5.html#pscp
Once you set up ssh-keygen as explained above, you can do
scp -i ~/.ssh/id_rsa /local/path/to/file remote#ip.com:/path/in/remote/server/
If you want to lessen typing each time, you can modify your .bash_profile file and put
alias remote_scp='scp -i ~/.ssh/id_rsa /local/path/to/file remote#ip.com:/path/in/remote/server/
Then from your terminal do source ~/.bash_profile. Afterwards if you type remote_scp in your terminal it should run the scp command without password.
Here's a poor man's Linux/Python/Expect-like example based on this blog post: Upgrading simple shells to fully interactive
TTYs. I needed this for old machines where I can't install Expect or add modules to Python.
Code:
(
echo 'scp jmudd#mysite.com:./install.sh .'
sleep 5
echo 'scp-passwd'
sleep 5
echo 'exit'
) |
python -c 'import pty; pty.spawn("/usr/bin/bash")'
Output:
scp jmudd#mysite.com:install.sh .
bash-4.2$ scp jmudd#mysite.com:install.sh .
Password:
install.sh 100% 15KB 236.2KB/s 00:00
bash-4.2$ exit
exit
Make sure password authentication is enabled on the target server. If it runs Ubuntu, then open /etc/ssh/sshd_config on the server, find lines PasswordAuthentication=no and comment all them out (put # at the start of the line), save the file and run sudo systemctl restart ssh to apply the configuration. If there is no such line then you're done.
Add -o PreferredAuthentications="password" to your scp command, e.g.:
scp -o PreferredAuthentications="password" /path/to/file user#server:/destination/directory
make sure you have "expect" tool before, if not, do it
# apt-get install expect
create the a script file with following content. (# vi /root/scriptfile)
spawn scp /path_from/file_name user_name_here#to_host_name:/path_to
expect "password:"
send put_password_here\n;
interact
execute the script file with "expect" tool
# expect /root/scriptfile
copy files from one server to other server ( on scripts)
Install putty on ubuntu or other Linux machines. putty comes with pscp. we can copy files with pscp.
apt-get update
apt-get install putty
echo n | pscp -pw "Password#1234" -r user_name#source_server_IP:/copy_file_path/files /path_to_copy/files
For more options see pscp help.
Using SCP non interactively from Windows:
Install the community Edition of netcmdlets
Import Module
Use Send-PowerShellServerFile -AuthMode password -User MyUser -Password not-secure -Server YourServer -LocalFile C:\downloads\test.txt -RemoteFile C:\temp\test.txt for sending File with non-interactive password
In case if you observe a strict host key check error then use -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null options.
The complete example is as follows
sshpass -p "password" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root#domain-name.com:/tmp/from/psoutput /tmp/to/psoutput
You can use below steps. This works for me!
Step1-
create a normal file suppose "fileWithScpPassword" which contains the ssh password for the destination server.
Step2- use sshpaas -f followed by password file name and then normal scp command.
sshpass -f "fileWithScpPassword" scp /filePathToUpload user#ip:/destinationPath/
One easy way I do this:
Use the same scp cmd as you use with ssh keys i.e
scp -C -i <path_to opens sshkey> <'local file_path'> user#<ip_address_VM>: <'remote file_path’>
for transferring file from local to remote
but instead of providing the correct <path_to_opensshkey>, use some garbage path. Due to wrong key path you will be asked for password instead and you can simply pass the password now to get the work done!
An alternative would be add the public half of the user's key to the authorized-keys file on the target system. On the system you are initiating the transfer from, you can run an ssh-agent daemon and add the private half of the key to the agent. The batch job can then be configured to use the agent to get the private key, rather than prompting for the key's password.
This should be do-able on either a UNIX/Linux system or on Windows platform using pageant and pscp.
All the solutions mentioned above can work only if you the app installed or you should have the admin rights to install except or sshpass.
I found this very useful link to simply start the scp in Background.
$ nohup scp file_to_copy user#server:/path/to/copy/the/file > nohup.out 2>&1
https://charmyin.github.io/scp/2014/10/07/run-scp-in-background/
I found this really helpful answer here.
rsync -r -v --progress -e ssh user#remote-system:/address/to/remote/file /home/user/
Not only you can pass there the password, but also it will show the progress bar when copying. Really awesome.

Script to check passwordless connectivity between servers

I have the following script. My requirement is if I give the username and IP address the script should check whether the host server has passwordless connectivity with the given server.
script.sh
#!/bin/sh
echo "Enter username"
read user
echo "Enter IP address"
read ip
echo "Enter condition"
read conditon
if [ $condition == "test" ]
then
ssh -o 'PreferredAuthentications=publickey' $user#$ip "echo"
fi
The above script checks for passwordless connectivity and exits. I want the script to return "success" if the connection is there or "No connection" if there is no passwordless connection between the hosts.
Thanks.
You can give an extra option to ssh that sets it in BatchMode
BatchMode
If set to yes, passphrase/password querying will be disabled. This option is useful in scripts and other batch jobs where no user is present to supply the password. The argument must be yes or no (the default).
source: man sshconfig
The following line will return the requested error code
ssh -oBatchMode=yes user#server echo > /dev/null 2>&1
This will return 0 if it can log in and will return a non-zero value (255) if it fails to login.
So you could do something like:
ssh -oBathMode=yes "${user}#${server}" echo > /dev/null 2>&1 && echo "Success" || echo "No Connection"
Or you could even let the server answer Success as
ssh -oBathMode=yes "${user}#${server}" echo Success 2>/dev/null || echo "No Connection"
Prerequisites
Access to command line/terminal window
User with sudo or root privileges
A local server & a remote server
SSH access to a remote server via command line/terminal window
Before You Start
Check for existing SSH Keys, using the below command
ls -al ~/.ssh/id_*.pub
If the output tells you there are no such files, move on to the next step, which shows you how to generate SSH keys.
Step 1: Generate SSH Key Pair
ssh-keygen -t rsa -b 4096 -C "your_email#domain.com"
Next, type in the path where you want to store the keys or hit
Enter to accept the default path.
It also asks you to set a passphrase, this is to ensure more secure connection. Note that, the Passphrase may be interrupted when you set up automated processes. Else, one can just press Enter to skip this step.
The output shows you the identification & about where is your public key stored along with the key fingerprints.
Verify your newly created SSH key pair, using the below command.
ls -al ~/.ssh/id_*.pub
Step 2: Uploading the Public Key to Remote Server
There are 2 options, that one can adopt:
Using ssh-copy-id Command
Using cat Command
Using ssh-copy-id command
ssh-copy-ide [remote_username]#[server_ip_address]
Using cat Command
ssh [remote_username]#[server_ip_address] mkdir -p .ssh
Type in the password for remote server, and then cat to view the contents of the stored Public Key
cat .ssh/id_rsa.pub | ssh [remote_username]#[server_ip_address] 'cat >> .ssh/authorized_keys'
Step 3: Log in to Server Without Password
Final step is to check whether the setup works fine or not.
ssh [remote_username]#[server_ip_address]
Troubleshooting, if found any errors
If you are still prompted for a password after going through all the steps, start by editing file permissions on the remote server.
Set permissions 700 for the .ssh directory.
Set permissions 640 for the .ssh/authorized_keys directory.
Edit file permissions using this command:
ssh [remote_username]#[server_ip_address] "chmod 700 .ssh; chmod 640 .ssh/authorized_keys"
References:
(https://stackoverflow.com/a/52744882/18154805)

getting multiple issues while creating a script to update hostnames in /etc/hosts file?

We've around 3000 VMs & 450 Physical servers which are Linux based servers (few of then ubuntu starting from 9.x & few of them are Susu starting 8.X & majority of them are RHEL starting from 4.x till 7.4) on all of them I need to add few hostname entries with IP details into their respective /etc/hosts files.
I've different users on each server with full sudoers access which I can use
Hence I've created a CSV file with hostname, username & password format. which contains required details to log in. Filename is "hostname_logins.csv"
I need to upload a file (i.e. hostname_list to each of these servers and then update those same details in each of the servers host files.
I'll be running this script using one RHEL 6 server. (All of the other hosts are resolvable from this server & are reachable, I've confirmed it already.)
The script is working but it's asking for accepting the host key once and also asked for the password 2 times however the 3rd time it does not asked for a password it worked automatically I guess, but need to ensure it does not askes to accept the host key or passwords.:
#!/bin/bash
runing_ssh()
{
while read hostname_login user_name user_password
do ssh -vveS -ttq rishee:rishee#192.168.1.105 "sudo -S -ttq < ./.pwtmp cp -p /etc/hosts /etc/hosts.$(date +%Y-%m-%d_%H:%M:%S).bkp && sudo -S bash -c 'cat ./hostname_list >> /etc/hosts' && rm -f ./.pwtmp ./hostname_list"
done < hostname_logins.csv
}
while read hostname_login user_name user_password
do echo $user_password > ./.pwtmp
cat ./.pwtmp
scp -p ./.pwtmp ./hostname_list $user_name#$hostname_login:
runing_ssh
done < hostname_logins.csv
I need to make this as a single script which will work on all these servers. thanks in advance.
You are executing the original copy from /tmp with sudo, but nothing else.
while read hostname_login user_name user_password
do echo $myPW >.pwtmp
scp -p ./.pwtmp ./hostname_list $user_name:$user_password#$hostname_login:
ssh -etS $user_name:$user_password#$hostname_login "sudo -S <.pwtmp cp -p /etc/hosts /etc/hosts.bkp && sudo -S <.pwtmp cat ./hostname_list >> /etc/hosts && rm -f ./.pwtmp ./hostname_list"
done < hostname_logins.csv
I dropped the explicit send to /tmp and the cp back to your home dir, and defaulted the location (to $user_name's home dir) by not passing anything to scp after the colon. Fix that if it doesn't work for you.
I created a password file for improved security and code reuse, and sent it along with the hosts list. I added a sudo -S to each relevant command, reading from the password file.
That [bash -c ...] syntax doesn't work on my implementation, so I took it out.
Hope that helps.
Update
Added -t to ssh call. Try that.

Resources