Set custom variable in capistrano 3 - capistrano

I was using capistrano 2 with my php project, where I used to define custom variables like this:
set :app_environment, "test"
And then I accessed it in my deploy tasks, e.g.:
run "echo '#{app_environment}' > #{releases_path}/#{release_name}/protected/config/mode.php"
Now in capistrano 3 I define this variable in my stage-specific config files. But I don't have them defined in my tasks:
undefined local variable or method `app_environment' for #<SSHKit::Backend::Netssh:0x007f92323d6988> config/deploy.rb:28:in `block (3 levels) in <top (required)>'
Unfortunately there's not much documentation on the newest version of capistrano and I'm not quite familiar with ruby, so I don't see the way how to do that properly.

The code should read:
run "echo '#{fetch(:app_environment)}' > #{releases_path}/#{fetch(:release_name)}/protected/config/mode.php"
Although even that is incorrect as run() doesn't exist in Cap3, it's now execute(), so:
execute "echo '#{fetch(:app_environment)}' > #{releases_path}/#{fetch(:release_name)}/protected/config/mode.php"
Beware constructing your command like this nothing will use the command map, or respect the within(), as() or with() constructs.

This is now achieved via 'fetch':
fetch(:app_environment)

Related

How can I run external programs using Perl 6? (e.g. like "system" in Perl 5)

I can use system in Perl 5 to run external programs. I like to think of system like a miniature "Linux command line" inside Perl. However, I cannot find documentation for system in Perl 6. What is the equivalent?
Perl6 actually has two commands that replace system from Perl 5.
In Perl6, shell passes its argument to the shell, similar to Perl 5's system when it has one argument that contains metacharacters.
In Perl6, run tries to avoid using the shell. It takes its first argument as a command and the remaining arguments as arguments to that command, similar to Perl 5's system when it has multiple arguments.
For example:
shell('ls > file.log.txt'); # Capture output from ls (shell does all the parsing, etc)
run('ls','-l','-r','-t'); # Run ls with -l, -r, and -t flags
run('ls','-lrt'); # Ditto
See also this 2014 Perl 6 Advent post on "running external programs".
In addition to using shell or run, which replace system from Perl 5, you can also use NativeCall to invoke the libc system function.
On my Windows box, it looks like this:
use NativeCall;
sub system(Str --> int32) is native("msvcr110.dll") { * };
system("echo 42");

How to access command line parameters in build definition?

I'd like to be able to modify some build tasks in response to command line parameters. How do I (can I?) access command line parameters from the Build.scala file?
I don't think it's possible and you should rather resort to using input tasks or environment properties with -D.

supervisor program:x command expansion of environment variables $(ENV_VAR)s?

I would like to put configuration (in this case, site name) into supervisor
environment variables, for expansion in program:x command arguments. Is this supported? The documentation's wording would seem to indicate yes.
The following syntax is not working for me on supervisor-3.0 (excerpt of config file):
[supervisord]
environment = SITE="mysite"
[program:service_name]
command=/path/to/myprog/myservice /data/myprog/%(ENV_SITE)s/%(ENV_SITE)s.db %(program_name)s_%(process_num)03d
process_name=%(program_name)s_%(process_num)03d
numprocs=5
numprocs_start=1
Raises the following error:
sudo supervisord -c supervisord.conf
Error: Format string
'/path/to/myprog/myservice /data/myprog/%(ENV_SITE)s/%(ENV_SITE)s.db %(program_name)s_%(process_num)03d'
for 'command' contains names which cannot be expanded
Reading the documentation, I expected environment variables to be available for
expansion in program:x command as %(ENV_VAR)s:
http://supervisord.org/configuration.html#program-x-section-values
command:
"String expressions are evaluated against a dictionary containing the keys
group_name, host_node_name, process_num, program_name, here (the directory of
the supervisord config file), and all supervisord's environment variables
prefixed with ENV_."
Introduced: 3.0
Related:
There are open pull requests to enable expansion in additional section values:
https://github.com/Supervisor/supervisor/issues?labels=expansions&page=1&state=open
A search of goole (or SO) returns no examples of attempts to use %(ENV_VAR)s
expansion in the command section value:
https://www.google.com/search?q=supervisord+environment+expansion+in+command
I agree supervisor is not clear about this ( to me at least ).
I've found the easiest solution to execute /bin/bash -c.
In your case it would be:
command=/bin/bash -c"/path/to/myprog/myservice /data/myprog/${SITE}/${SITE}.db ..."
What do you think?
I've found inspiration here: http://blog.trifork.com/2014/03/11/using-supervisor-with-docker-to-manage-processes-supporting-image-inheritance/
You are doing it right; however, the ENV defined in your supervisord section doesn't get made available to the processes for whatever reason during configuration loading. If you start supervisord like this:
SITE=mysite supervisord
It will run correctly and expand that variable. I don't know why supervisord has issues adding to the environment and making it available to the subprocesses' config expansion. I think the environment variable is available inside the subprocess, but not when expanding variables in the subprocess config declaration.

Phing exec command to set environment variable

I'm trying to set an environment variable in a build script with phing.
This is normally done command line like this:
export MY_VAR=value
In Phing I did the following but it isn't working.
<exec command="export MY_VAR=value" />
I see that this is quite an old question, but I don't think it has been answered in the best way. If you wish to export a shell variable, for example say you are running phpunit from phing and want to do an export before invoking phpunit, try:
<exec command="export MY_VAR=value ; /path/to/phpunit" />
Simply do the export and invoke your command inside the same exec tag. Separate the export statement and the shell executable with a semicolon as shown. Your script will be able to access the value using the standard php function:
$myVar = getenv('MY_VAR');
Bold claim: There is no way to set/export a (Unix) shell variable in PHP so that it is visible inside the scope that started the php script.
php myfile.php (does putenv or shell_exec('export foo=bar');)
echo $foo
Will return nothing.
As PHP can not do it so neither can phing.
Accessing shell environment variables accross multiple script runs (if its that what you want) seems also like an unideal design decision, pretty stateful.
Apart from that I'd urge you to stick to phing and learn its lean lesson. Phing helps stateless thinking to some degree.
I'd never heard of phing before, but this looks very promising as a build tool. Thanks for posting! I looked through the doc on phing.info, I found the following possibility:
#0 I would like to clarify one point. Are you saying that
prompt$ > export MY_VAR=value
prompt$ > phing build.xml
doesn't set MY_VAR to value so it is visible inside the running phing processes? I'd be surprised, but I would understand if this is not how you want to run your build script.
#1 I think in the context of a build tool, a feature like exec is meant to run a stand-alone program, so, while the exec may run and set MY_VAR, this is all happening in a subprocess that disappears immediately as the exec finishes and continues processing the next task in the build.xml.
If you're just trying to ensure that your phing script runs with specific values for env_vars, you could try
Command-line arguments:
....
-D<property>=<value>
// Set the property to the specified value to be used in the buildfile
So presumably, you can do
phing -DMY_VAR=value build.xml
#2 did you consider using a properites file?
See http://www.phing.info/docs/guide/stable/chapters/appendixes/AppendixF-FileFormats.html
and scroll down for info on build.properties
#3 also ...
Phing Built-In Properties
Property Contents
env.* Environment variables, extracted from $_SERVER.
you would access them with something like
${env.MY_VAR}
#4 This looks closer to what you really want
<replacetokens>
<token key="BC_PATH" value="${top.builddir}/"/>
<token key="BC_PATH_USER" value="${top.builddir}/testsite/user/${lang}/"/>
</replacetokens>
I hope this helps.

Why can't my Perl script load a module when run by cron?

I have a bunch of Perl scripts that all run fine, yet need to have use Plibdata; up top.
I set up a cron job that runs (I get the confirmation email from root) and it spits back the following error message:
Can't locate Plibdata.pm in #INC (#INC contains: /install/lib /opt/perl58/lib/5.8.8/IA64.ARCHREV_0-thread-multi /opt/perl58/lib/5.8.8 /opt/perl58/lib/site_perl/5.8.8/IA64.ARCHREV_0-thread-multi /opt/perl58/lib/site_perl/5.8.8 /opt/perl58/lib/site_perl .) at ./x line 5.
BEGIN failed--compilation aborted at ./x line 5.
Line 5 is... you guessed it.... use Plibdata;
I am also attempting to set the environment as such:
use lib "$ENV{CARSPATH}/install/lib";
so maybe if I found the location of this plibdata, I could explicitly direct it that way?
My cron commands will be executed using /usr/bin/sh says crontabs...
Any suggestions?
This script works from the command line.
You don't say what Plibdata is. You also don't state if this works at your command prompt. I assume that it does.
Try this:
perl -MPlibdata -e 1
Assuming that doesn't spit the same error, try this:
perl -MPlibdata -le 'print $INC{"Plibdata.pm"}'
That will tell you where. (It's probably in your PERL5LIB env var if this works.) Then you can just add the appropriate "use lib" to the directory Plibdata.pm is in.
Also, be sure you're using the same perl in both locations - command line ("which perl") and in the cron job (try "BEGIN { print $^X }" at the top of your script).
Cron uses a different user env than your env when logged in. Are you able to run the script from the command line? If so, just set your env variables inside the cron above your current commands.
Clearly, Plibdata.pm is not installed in the default module paths on your system:
/install/lib /opt/perl58/lib/5.8.8/IA64.ARCHREV_0-thread-multi /opt/perl58/lib/5.8.8 /opt/perl58/lib/site_perl/5.8.8/IA64.ARCHREV_0-thread-multi /opt/perl58/lib/site_perl/5.8.8 /opt/perl58/lib/site_perl
You have three choices:
Install Plibdata.pm in a known Perl system path (site_perl is the classic option).
Make the PERL5LIB shell environment (or the equivalent command line -I option for Perl) include the installation path of the module.
Use use lib in your script. Remember that the use lib action is done at compile time, so your variable in the path may not be initialised. Try using the variable in a BEGIN block like this:
my $env;
BEGIN {
$env = $ENV{CARSPATH};
}
use lib "$env/install/lib";
Running your program from a wrapper script as others have suggested is probably my preferred method, but there may be a few other solutions:
If you're using a modern cron you may be able to do something like this in your crontab entry:
* * * * * CARSPATH=/opt/carsi x
replacing the asterisks with the appropriate schedule designators.
This will set CARSPATH for the x process and allow the use lib statement that passes the environment variable to work.
You can also, depending on your shell and cron implementation, store your environment setup in a file and do something like:
* * * * * source specialenv.sh && x
Where specialenv.sh contains lines like (for bash)
export CARSPATH=/opt/carsi
You may also be able to set environment variables directly in the crontab, should you choose to do so.
cron does not setup an environment for you when it runs your code, so the environment variable $CARSPATH does not exist. I suggest only running shell scripts from cron, setting the environment inside of the shell script and then running the program you really wanted to run.
example wrapper script:
#!/bin/bash
source ~username/.bash_profile
cd ~username
./script.pl
If you are using ksh or sh you may need to say
#!/bin/sh
. ~username/.profile
cd ~username
./script.pl
Remember to replace username with your username on the system. Also, if the script is not in your home directory you will want to execute it with the path to it, not ./.
You say source, or period space, to load a given shell script in the current shell. You load it in the current shell so that any environment settings stay with the current shell.
~/.bash_profile, ~/.bashrc, ~/.profile, /etc/profile, etc. are all files that commonly hold your environment setup. Which one you are using depends heavily on your OS and who set it up.
Although its not an 'answer', I resolved this issue by using DBI instead of the Plibdata.
Which is kind of milky because now I will have to change a couple scripts around... ahhhhh I wish there was something I could do to make the Plibdata work
I'm still going to try Chas. Owens answer to see if that works
didn't work for me... "interpreter "/bin/bash" not found"maybe it would work with people who have that interpreter
* * * * * CARSPATH=/opt/carsi ./x
works