Set umask for remote commands - capistrano

How can I direct processes started on remote machines via ssh to run with a certain umask? I want this to apply to commands run as part of standard Capistrano recipes too, so I can't just make an explicit call to "umask" part of the command.
It does not appear that ~/.bash_profile on the remote machine is read, with the way that Capistrano invokes remote commands.

I was confronted to the same issue and got around it by using the then-undocumented SSHKit.config.umask in config/deploy.rb. Note that this will set the umask for every ssh command.

Put umask 0002 in the .bashrc of the user account you use to deploy.

Agreed with Alain--set the umask in your .bashrc instead of .bash_profile. When deploying with Capistrano in a typical setup, your .bash_profile isn't loaded by default. Reading up on the difference between .bashrc and .bash_profile will help in understanding the purposes of the two.
I have environment variables set in my .bashrc file and they are certainly used when I deploy or for running any other commands with capistrano.
Another option is to create a task to set your umask value before you begin creating files on deploy. For example, in Cap 3, you can use this:
task :set_umask do
on roles(:all) do |host|
execute "umask 0002"
end
end
before "deploy:starting", "set_umask"

#beauby's answer using SSHKit is good, but it works only for Capistrano 3 as Capistrano 2 doesn't use SSHKit.
A common problem in relation to umask and Capistrano is that bundle install installs gems with permissions that are too restrictive. For this specific issue, the solution I've found for Capistrano 2 is to say:
namespace :bundle do
task :postinstall do
run "chmod -R u=rwX,go=rX #{bundle_dir}"
end
end
after 'bundle:install', 'bundle:postinstall'

Related

Set global environment variables in VS Code with remote-ssh

I have the case that I need to use VS Code installed on Windows 10 and run it with the extension Remote - SSH on a RHEL 7.x.
The default RHEL 7.x runs with git 1.8.x. I have installed a newer git version but this is not in the default $PATH environment.
I have found this instructions https://code.visualstudio.com/docs/remote/wsl#_advanced-environment-setup-script which describe how to set the environment variables specifically for VS Code when usind WSL.
If you want to run additional commands or modify the environment this can be done in a setup script ~/.vscode-server/server-env-setup
This does seem to work only if you use WSL. Why does this not work with the Remote - SSH extension?
My special case is that I only want and need the git>=2 while usind VS Code. When I am connected regularly via ssh I would like and need the OS default tools and settings.
This gives me the special request that I don't want to edit the ~/.bashrc, ~/.cshrc or any other user environment files.
I would like to be able to edit the environment for VS Code only. Some kind, maybe like:
#!/bin/bash
export PATH=/opt/rh/rh-git29/root/usr/bin\:$PATH
export LD_LIBRARY_PATH=/opt/rh/httpd24/root/usr/lib64:$LD_LIBRARY_PATH
...
#!/bin/csh
setenv PATH /opt/rh/rh-git29/root/usr/bin\:$PATH
setenv LD_LIBRARY_PATH /opt/rh/httpd24/root/usr/lib64:$LD_LIBRARY_PATH
...
Is there anything I have not found yet where I can make my requests to work or would this be some kind of request to the VS Code Team?
Regards.
I think I found the solution in this issue comment and the follow-up response:
When vscode-server initially starts, it uses a login shell, sourcing .profile in your home directory.
However, any following interactive shells started through VS Code are non-login shells and thus only source .bashrc
A complication in fiddling with this is that vscode-server apparently caches the environment during its lifetimes, so changes to these dotfiles don't become visible until the server is restarted.
I have a better solution to minimize the proxy scope
export http_proxy=<proxy here>
export no_proxy=<no proxy here>
while IFS= read -r _file; do
if ! grep -s -q "export http_proxy=" "${_file}"; then
sed -i -e "/^ROOT/i export http_proxy=${http_proxy}" -e "/^ROOT/i export https_proxy=${http_proxy}" -e "/^ROOT/i export no_proxy=${no_proxy}" "${_file}"
fi
done < <(find ~/.vscode-server/bin -type f -name "server.sh")

How to load environment variables in a remote AIX machine through ssh while running script from Jenkin pipeline?

We are using some custom modules in our Perl automation framework which runs through Jenkin pipeline. Recently we got package not found error for all custom modules while executing test cases in AIX servers as latest Perl version is installed there . So we tried to add "PERL5LIB" in the path as mentioned in document
https://perlmaven.com/how-to-change-inc-to-find-perl-modules-in-non-standard-locations
We added "export PERL5LIB=/home/foobar/code" in /etc/profile of the AIX server and script getting executed without any issue when running from local AIX machine.
Issue:
But we have Jenkin pipeline to execute the scripts in AIX server using ssh. Now when we do SSH to the AIX server in the pipeline script the variables that we have set in /etc/profile does not load and we get package not found error.
Question: How can I load the profile in the AIX server while running it from pipeline? or is there any other way to handle this. Before executing script I want to export PERL5LIB in remote AIX server through pipeline (only once) and the I should not get package not found error.
Below solutions I have tried :
Load the /etc/profile: ssh AIX server ./etc/profile (using dot since source not working in AIX)
Adding this line "export PERL5LIB=/home/foobar/code" in .ssh/environment in AIX server and set PermitUserEnviorment yes
Appreciate any help on this.
Assign values to variables the usual way:
ssh user#host 'export PERL5LIB=/somepath; echo $PERL5LIB'
user#hosts's password:
/somepath
or
ssh user#host '. /etc/profile.local; echo $PERL5LIB'
user#hosts's password:
/somepath/from/profile
Edit:
If you have to execute multiple commands, create a script and upload it to the target computer, for example:
SCRIPTNAME=/tmp/$$.$RANDOM.script
scp myscript.sh user#host:"$SCRIPTNAME"
ssh user#host "$SCRIPTNAME"
This is solved with below changes.
Step 1: Edit ~/.ssh/environment. Add variable PERL5LIB="/path of the module/"
Step 2: Edit /etc/ssh/sshd_config. Change variable PermitUserEnvironment from no to yes. Uncomment it if commented. This will enable access of environment variables to SSH.
Step 3: Restart SSHD service. (This is imp. I had tried step 1 and 2 before also but not restarted the service so solution was not working)
We can create a script and run it before executing automation test from pipeline.

Perl script works but not via CRON

I have a perl script (which syncs delicious to wp) which:
runs via the shell but
does not run via cron (and i dont get an error)
The only thing I can think of is that it read the config file wrongly but... it is defined via the full path (i think).
I read my config file as:
my $config = Config::Simple->import_from('/home/12345/data/scripts/delicious/wpds.ini',
\my %config);
(I am hosted on mediatemple)
Does anybody have a clue?
update 1: HERE is the complete code: http://plugins.svn.wordpress.org/wordpress-23-compatible-wordpress-delicious-daily-synchronization-script/trunk/ (but I have added the path as above to the configuration file location as difference)
update 2: crossposted on https://forums.mediatemple.net/viewtopic.php?pid=31563#p31563
update 3: the full path did the trick, solved
The difference between a cron job and a job run from the shell is 'environment'. The primary difference is that your profile and the like are not run for a cron job, so any environment variables you have set in your normal shell environment are not set the same in the cron environment - no extensions to PATH, no environment variables identifying where Delicious and/or WP are hosted, etc.
Suggestion: create a cron job that simply reports the environment to a known file:
env > /home/27632/tmp/env.27632
Then see what is set in your own shell environment in comparison. Chances are, that will reveal the trouble.
Failing that, other environmental differences are that a cron job has no terminal, and has /dev/null for input and output - so interactive stuff does not work well.
it seems the problem is not in running perl, but locating the Config library
you should try:
perl -e "print #INC"
and run a similar perl script in cron, and read the output
it possible that they differ
I suggest looking at my answer to How to simulate the environment cron executes a script with?
This is an similar Jonathan's answer but goes a bit further.
Based on your crontab, and depending on your installation, the problem might be the "perl". As others note the environment, particularly the $PATH variable, is different for cron. perl may not be in the path so you need to put the full path to perl in the cron command.
You can determine the path with the command $ type perl
I run into the same problem ...
Perl script works but not via CRON => error: "perl: command not found"
... after an update from Plesk 12.0 to Plesk 12.5. But the existing answers were not very helpful for me.
It took some time, but than I found this thread in the Odin forum which helps me: https://talk.plesk.com/threads/scheduled-tasks-always-fail.331821/
They suggest the following:
/usr/local/psa/bin/server_pref -u -crontab-secure-shell ""
That deletes in the /var/spool/cron/crontabs files the line:
SHELL="/opt/psa/bin/chrootsh"
After that, my cron jobs run with out any error.
(Ubuntu 14.04 with Plesk 12.5)
If the perl script runs fine manually, but not from crontab, then
there is some environment path needed by the some package that is not
getting through `cron`. Run your command as follows:
suppose your cron entry like:
* 13 * * * /usr/bin/perl /home/username/public_html/cron.pl >/dev/null 2>&1
env - /home/username/public_html/cron.pl
The output will show you the missing package. export that package path in
$PATH variables

Permission denied (publickey,keyboard-interactive)

Permission denied (publickey,keyboard-interactive) got this error while i am trying to cvs checkout from perl.
what is issue and how to reslove this ?
Code :
system ( "CSVROOT:--- CVSRSH:--- cvs co a ");
# i have proper value in cvs root and cvs rsh .
its running alone and using ssh key
Steps to diagnose the error:
Are you using an SSH key?
Does that key have a passphrase?
Does it work when you run it by hand?
Is the script running as the same user as when you run it by hand?
Is the script running under the same environment as when you run it by hand? (e.g. cron jobs do not run under the same environment)
If you think all of the answers are yes, then most likely the last answer is really no. If the script is running from a scheduler like cron it most likely does not run with the same environment as when you run it by hand. The way I normally solve this is to use a shell script between the scheduler and the Perl script:
#!/bin/bash
source /home/USERNAME/.profile
#set any other environment variables it needs like
export CSVROOT=:pserver:USERNAME#HOST:/path/to/repo
export CVSRSH=ssh
/path/to/perl/script/script.pl
Follow-up investigations after Chas.'s questions:
Does that command normally run under /bin/sh or some other shell?
To test, execute /bin/sh command to start Bourne shell and try the command by hand again.
I'm not familiar with "CVSROOT:---" notation - is that meant to set CVSROOT environmental variable? In Bourne shell it's usually done using "=", never saw ":" used.
Does the command, when run by hand, expect some input from you? I never saw cvs co to do so, but I don't use it with ssh.
Try to add a redirect to the end of the command and look what's in the file after running:
system ( "CSVROOT:--- CVSRSH:--- cvs co a > /tmp/log_cmd 2>&1");

Is it possible to have Perl run shell script aliases?

Is it possible to have a Perl script run shell aliases? I am running into a situation where we've got a Perl module I don't have access to modify and one of the things it does is logs into multiple servers via SSH to run some commands remotely. Sadly some of the systems (which I also don't have access to modify) have a buggy SSH server that will disconnect as soon as my system tries to send an SSH public key. I have the SSH agent running because I need it to connect to some other servers.
My initial solution was to set up an alias to set ssh to ssh -o PubkeyAuthentication=no, but Perl runs the ssh binary it finds in the PATH instead of trying to use the alias.
It looks like the only solutions are disable the SSH agent while I am connecting to the problem servers or override the Perl module that does the actual connection.
Perhaps you could put a command called ssh in PATH ahead of the ssh which runs ssh as you want it to be run.
Alter the PATH before you run the perl script, or use this in your .ssh/config
Host *
PubkeyAuthentication no
Why don't you skip the alias and just create a shell script called ssh in a directory somewhere, then change the path to put that directory before the one containing the real ssh?
I had to do this recently with iostat because the new version output a different format that a third-party product couldn't handle (it scanned the output to generate a report).
I just created an iostat shell script which called the real iostat (with hardcoded path, but you could be more sophisticated), passing the output through an awk script to massage it into the original format. Then, I changed the path for the third-party program and it started working fine.
You could declare a function in .bashrc (or .profile or whatever) with that name. It could look like this (might break):
function ssh {
/usr/bin/ssh -o PubkeyAuthentication=no "$#"
}
But using a config file might be the best solution in your case.