I rely a lot on core dumps for finding and fixing rare bugs on my personal applications.
I have multiple versions of my applications installed side by side, and decide which one to run (it depends on some other applications). Only one version of the same tool can run at any given time. My launchers start with "ulimit -c unlimited". When/if the application crashes, a core dump is generated.
One issue is that "file somecoredump" tells me the name of the process generated the core file, but I have no way to know which version of the application generated it, so it's not easy to tell which executable to use.
I'm wondering how this issue can be solved?
I can think of a couple of bad ways:
Embed the version info into the process name, such as MyProcess2.1c. Now "file corefile" tells me the version. Really ugly, I won't consider it.
Every launcher modifies /proc/sys/kernel/core_pattern and sets it to a path with the version info, such as /var/crash/2.1c/core. Ugly, because this setting affects all apps, not just mine. Also it only works now because I only allow a single version of the app to run at the same time, one day I might need to run multiple versions side-by-side.
What would be ideal for me is if there was a way to embed version info into the executable, and retrieve it from the core file. Is this possible?
You can use the strings command in linux to look for unique strings in a binary file. Perhaps you can compile the version into the binary such as this examnple from bash and then grep all the strings output to find it. Just prefix it with a unique string to make it easier to find?:
~]$ strings /usr/bin/bash | grep version
shell_version_string
build_version
sccs_version
rl_library_version
rl_do_lowercase_version
show_shell_version
rl_readline_version
dist_version
GNU bash, version %s-(%s)
GNU bash, version %s (%s)
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
#(#)Bash version 4.2.46(2) release GNU
display-shell-version
-l do not print tilde-prefixed versions of directories relative
HOSTTYPE The type of CPU this version of Bash is running under.
OSTYPE The version of Unix this version of Bash is running on.
version, type `enable -n test'.
do-lowercase-version
.gnu.version
.gnu.version_r
~]$
I have a script that must be run in Perl 5.10.1, although my university's linux cluster system uses the most recent version of Perl. I tried to install Perlbrew, but I don't think it worked.
I'm not sure how to specify the perl version in the shebang because of how I call/run this script. There is "cluster.pl", which is run by running "./command.txt".
Also, I don't think I can install Perlbrew because it's the university's linux system: After copy-pasting the installation commands, my terminal screen said the perlbrew patch was installed, but when I used "perlbrew install perl-5.10.1", it would say "command perlbrew not found" I don't know how to run the script
As of now, cluster.pl has this shebang:
#!/usr/bin/perl
One related question said to write this in the command line
/program/perl_v5.6.1/bin/perl scriptName.pl
#OP needed to use version 5.6.1, unlike me (I need 5.10.1)
However, I don't know whether "program" is OP's directory or a mandatory part of the path
Below is command.txt, which has the necessary input arguments:
#this is command.txt
./cluster.pl Datachr1 2 galGal5.Chroinfo.txt
Essentially, where would the suggested shebang go? Would I include "program" in my path too?
If you wrap your script in Perl's packaging framework, this is handled for you automatically. When it installs scripts, it changes the shebang line with the actual perl. You end up with something like this at the top of the file:
#!/usr/local/perls/perl-5.30.0/bin/perl
eval 'exec /usr/local/perls/perl-5.30.0/bin/perl -S $0 ${1+"$#"}'
if $running_under_some_shell;
#!/usr/local/bin/perl
You might try this with my app-rhich distribution. Download the tarball and run the Makefile.PL with the perl you want. Run make and it builds stuff into the blib staging directory. You should see the modified shebang there:
$ /Users/brian/bin/perls/perl5.30.0 MAkefile.PL
Checking if your kit is complete...
Looks good
WARNING: Older versions of ExtUtils::MakeMaker may errantly install README.pod as part of this distribution. It is recommended to avoid using this path in CPAN modules.
Generating a Unix-style Makefile
Writing Makefile for App::rhich
Writing MYMETA.yml and MYMETA.json
$ make build
make: *** No rule to make target `build'. Stop.
$ make
cp lib/App/rhich.pm blib/lib/App/rhich.pm
cp script/rhich blib/script/rhich
"/usr/local/perls/perl-5.30.0/bin/perl" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/rhich
Manifying 1 pod document
Manifying 1 pod document
brian#otter app-rhich (master)[3125]
$ more blib/script/
#!/usr/local/perls/perl-5.30.0/bin/perl
package rhich;
use strict;
use warnings;
However, if your path to perl is a symlink to some other perl, this can get confused. I don't use perlbrew because I don't think it adds much other than saving you looking up a download URL. I install multiple perls (and How should I install more than one version of Perl?) and can use paths to them so I know which version using. There's a similar problem with env depending on how you set up your path. How you handle that is based on how you decide to manage things, but it's these sorts of questions that show that the tools of convenience aren't really that convenient.
recently, i try to compile a gnu wget from source code in cygwin environtment that pop-up error if perl is not found. otherwise, perl is installed both perl and perl5 on /bin/ but the wget is try search perl on /usr/bin. i think i have missed basic ./configure to setup path executable. so my question is basic.
what is it all about options on below:
*
--bindir=DIR
--sbindir=DIR
--libexecdir=DIR
*
Thank you
These options specify directories where a software package being compiled is going to be installed. As far as I remember it doesn't deal with checks performed by configure. Make sure that perl is in $PATH. If nothing helps, try to locate the exact place in the configure script (usually it's robot-generated and not intended for human eyes, but afterall it's a shell script, and anybody can read it) and see what checks exactly are performed to locate perl.
Update: I have checked, the tests corresponding to perl look like this in configure.ac (which essentially is a "source code" for configure):
AC_PATH_PROGS(PERL, [perl5 perl], no)
AC_PATH_PROG(POD2MAN, pod2man, no)
This means that PERL with executable named perl5 or perl (somewhere in $PATH) is checked, and then POD2MAN with executable pod2man. Carefully check the configure output and config.log file and see what tests have failed.
Update2: The third argument of the AC_PATH_PROG and AC_PATH_PROGS is value-if-no-found. Also you may specify the fourth argument, $PATH for this particular check. Make sure that configure gets rebuilt after you changed configure.ac (usually it happens automatically, but may be performed by autoconf explicitly)
what is it all about options on below:
*
--bindir=DIR
--sbindir=DIR
--libexecdir=DIR
The first (bindir), is where binaries will be installed. For wget, that's (on my system) /usr/bin.
The second (sbindir), is where static binaries will be installed. You might set that to /usr/sbin.
The third (libexecdir), is where your runtime libraries are to be installed. That's usually /usr/lib.
In fact, usually you let configure set all three by using --prefix.
./configure --prefix=/usr/local
I want to display some text in a script only if the Operating System is Centos .
How can i do that in a perl script ?
To answer your exact question, you can identify CentOS by reading the contents of /etc/redhat-release. E.g.
$ cat /etc/redhat-release
CentOS release 5.9 (Final)
As other commenters have made clear, it is better to depend on the exact OS features you want, or write code to be portable, rather than limiting it to a particular distribution of Linux.
Try $^O. It contains the OS that was used to build your version of Perl. Here's what perlvar has to say about it.
The name of the operating system under which this copy of Perl was
built, as determined during the configuration process. For examples
see PLATFORMS in perlport. The value is identical to $Config{'osname'}
. See also Config and the -V command-line switch documented in
perlrun. In Windows platforms, $^O is not very helpful: since it is
always MSWin32 , it doesn't tell the difference between
95/98/ME/NT/2000/XP/CE/.NET. Use Win32::GetOSName() or
Win32::GetOSVersion() (see Win32 and perlport) to distinguish between
the variants. This variable was added in Perl 5.003.
Also see perlport.
A recent question here on SO got me thinking.
On most Linux distributions that I tried, some Perl modules would be available through the package manager. Others, of course, not. For quite a while I would use my package manager whenever I needed to install some CPAN module to find out whether a package was available or not and to install it when it was.
The obvious advantage is that you get your modules updated whenever a new version of the package becomes available.
However, you get in trouble when the module is not available in pre-packaged form and there are dependencies for that module that are. Firing up your package manager every time the cpan shell asks whether it should follow a dependency can be quite tiring.
Often, another drawback is the version of the pre-packaged module. If you are running Debian or Ubuntu you will soon find out that you will not be able to live on the bleeding edge, like many CPAN module authors seem to do.
How do other Perl people on Linux handle that problem? Do you just ignore what your package managers have to offer? Are there any tools that make apt (for example) and cpan better team mates? Or do you simply not install anything via the cpan shell?
For development, I install my own Perl and leave the system Perl alone. If I want to upgrade the system Perl, I use the system package manager. For my development Perl, I use the cpan tool.
Since I keep those separate, I should never mess up the Perl that the system needs for its maintenance tasks and so on, but I don't have to rely on the system's decisions for development.
It's very easy to install separate Perls. When you run Configure from the source distribution, it will ask you where you want to install everything. Give it any path that you like. I have many Perls installed in /usr/local/perls, for instance, and everything for each installation lives separately. I then make symlinks in /usr/local/bin for them (e.g. perl5.8.9, perl.5.10.0, perl5.10.0-threaded). When I want a particular version, I just use the one I want:
$ perl5.10.0 program.pl
The particular binary ensures that the program picks up the right module search path and so on (it's the same stuff in the Config.pm module for that binary).
Here's a script I use to create the symlinks. It looks in the bin directory, figures out the Perl version, and makes links like cpan5.10.1 and so on. Each program already knows the right perl to call:
#!perl
use 5.010;
use strict;
use warnings;
use File::Basename;
use File::Spec::Functions;
my $perls_directory = catfile(
$ARGV[0] // '/usr/local/perls',
'perl*'
);
die "$perls_directory does not exist!\n"
unless -d dirname $perls_directory;
my $links_directory = $ARGV[1] // catfile( $ENV{HOME}, 'bin' ); #/
die "$links_directory does not exist!\n" unless -d $links_directory;
foreach my $directory ( glob( $perls_directory ) )
{
say "Processing $directory...";
unless( -e catfile( $directory, 'bin' ) )
{
say "\tNo bin/ directory. Skipping!";
next;
}
my #perls = glob( catfile( $directory, qw( bin perl5* ) ) );
my( $perl_version ) = $perls[0] =~ m/(5\.\d+\.\d+)\z/;
say "\tperl version is $perl_version";
foreach my $bin ( glob( catfile( $directory, 'bin', '*' ) ) )
{
say "\tFound $bin";
my $basename = basename( $bin );
my $link_basename = do {
if( $basename =~ m/5\.\d+\.\d+\z/) { $basename }
else { "$basename$perl_version" }
};
my $link = catfile( $links_directory, $link_basename );
next if -e $link;
say "\t\tlinking $bin => $link";
symlink $bin => $link or
warn "\t\tCould not create symlink [$!]: $bin => $link!";
}
}
Everything gets install in the right place for that particular Perl.
I've also been thinking that I should put those Perl directories under some sort of source control. If I add a module I don't like, I just back out to an earlier revision. I'm only starting to do that though and haven't played with it much.
I've written more about this sort of thing in the Effective Perler blog:
Make links to per-version tools.
Manage your Perl modules with Git.
We install everything via the CPAN shell. This does ignore what package managers have to offer, but it avoids the headaches you mention when trying to work with them (firing for dependencies, using correct versions).
In addition, it means that our packages can be built programatically (or manually via the shell) on any platform where CPAN runs. Having a dependency on a package manager would affect your ability to distribute your software to platforms that don't use/support that package manager.
Since this question was originally asked, perlbrew has been released. It makes installing custom, self-contained perl installs trivial. And switching between those versions is just as easy:
perlbrew switch $version
I am using Debian for development, and production, and rely on debian Perl packages that are provided with the distro.
For cases where I need a Perl module that is not available in debian, I usually create my own debian package of it and install it.
Ofcourse, this method is not without faults, as a a lot of debian perl modules are outdated (at least in the current debian stable version - etch), and backporting something like Catalyst which has lots of dependencies is not practical.
However, by relying on the OS package manager, I retain all the great features of it, which bring easy maintenance, especially for deployed servers, as you know exactly what packages are installed, and a simple apt-get update;apt-get upgrade (from debian, or from a local repository) upgrades all servers to the same state, including the Perl modules.
I do the following on all my boxes:
I compile my own perl: I still use 5.8.[89] mostly, the stock 5.10.0 has a performance regression that hits me a lot, waiting for 5.10.1 to try again;
I use (and strongly recommend) the local::lib module to keep a module directory per project. Right now, that directory is rsync'ed to all the servers where the project is installed, but I'm testing using git instead;
I create a Task:: module for each project, so that I can install all dependencies with a single command.
I also use the cpan shell and local::lib.
You shouldn't need a Task:: for each project. Just use Module::Install (I like to use Module::Starter like this:
$ module-starter --mi --module=Module::Name --author="Me" --email=me#cpan.org
and then just pop your dependencies in requires 'module::dependency'; in the Makefile.PL. Finally when it's install time, you just perl Makefile.PL (answer yes) then make installdeps
[edit 5 years on from when I gave this answer originally]
These days perlbrew and cpanm are the things to use. local::lib still has a use-case, but the combination of perlbrew and cpanm solve a superset of those cases. Use local::lib when you're not prepared to compile your own perl.
I recommend use only cpan. The modules includes in Linux distro is only to cover package dependency. When you are installing linux without internet access with only CDs, it can't use cpan, so some modules are included as packages, but to a Perl developer this is bad.
Also I used to have a cpan configured to install modules in my home, (.perl) without root login needed.
For production:
In development, choose a version of the perl module which seems right for the requirements; if possible choose the target OS's shipped version (this makes most of the following superfluous), otherwise, pick another one. Create a RPM spec file for it. Use the clean build VM to build the RPM in a reproducable way (from a specfile / source checked in on the appropriate branch).
When the final build can be built (after merge), do the same build from the release branch, commit generated RPMs into deployment repository. This will be used in final validation and then released to production by being copied to the production repository.
All servers in production use the exact same binary that has been fully tested; they use the same spec file and source as the developer intended.
Perl modules are NOT upgraded by any process which does not follow this model. Nor is any other production software.
I use FreeBSD ports and wrap up all the CPAN dependencies in a "meta port" as a sort of a local port. FreeBSD has quite a large number of CPAN modules and their build system is approachable enough that you can easily write your own port if it doesn't exist--just dont forget to submit said port so it gets included in the ports tree. If the port doesn't have the current version in stock, you can always edit the Makefile for the port so it uses the new version, again don't forget to submit the change :-).
Lastly, I use Tinderbox to build the whole mess as binary packages that I then install on the all the production and development machines.
Bottom line--Once you get over your phobia of editing Makefiles, FreeBSD's ports are a great way to maintain your perl application and its dependencies.
I have started using Gentoo recently and Gentoo has a few very important advantages in this area. The first is that g-cpan is capable usually of installing many (though not all) modules from CPAN as Gentoo packages natively, though updating becomes a bit of a problem.
Usually on Gentoo, my approach is to use g-cpan to create an ebuild file, then install from that, tweaking if necessary. The advantage is that upgrading becomes really easy. I then move the file from g-cpan/perl to dev-perl and put it in an overlay for others to use. This allows me to quickly handle the cases g-cpan does not and gentoo packaging is a breeze anyway/