推荐一个能上首页推荐的 perl 项目:: https://github.com/openresty/stapxx
#!/usr/bin/env perl
use strict;
use warnings;
use Getopt::Long qw( GetOptions :config no_ignore_case);
use File::Spec ();
use File::Temp qw( tempdir );
use FindBin ();
sub quote_sh_args ($);
GetOptions("D=s@", \(my $D_opts),
"c=s", \(my $shcmd),
"d=s@", \(my $d_opts),
"arg=s%", \(my $args),
"args", \(my $print_args),
"dump-src", \(my $dump_src),
"sample-pid=i", \(my $sample_pid),
"exec=s", \(my $exec_path),
"help", \(my $help),
"master=i", \(my $master_pid),
"x=i", \(my $pid),
"e=s", \(my $src),
"v", \(my $verbose),
"skip-badvars", \(my $skip_badvars),
"I=s@", \(my $Inc))
or die usage();
push @$Inc, '.', "$FindBin::Bin/tapset";
#warn "Inc: @$Inc\n";
if ($^O ne 'linux') {
die "Only linux is supported but I am on $^O.\n";
}
if ($print_args && $args && %$args) {
die "No --arg is allowed when --args is specified.\n";
}
my $ver = `stap -V 2>&1`;
if (!defined $ver) {
die "Systemtap not installed or its \"stap\" utility is not visible to the PATH environment: $!\n";
}
if ($ver =~ /version\s+(\d+\.\d+)/i) {
my $v = $1;
my $min_ver = 2.3;
if ($v < $min_ver) {
die "ERROR: at least systemtap $min_ver is required but found $v\n";
}
} else {
die "ERROR: unknown version of systemtap:\n$ver\n";
}
if ($help) {
print usage();
exit;
}
my %set_D_opts;
for my $opt (@$D_opts) {
#warn "$opt\n";
if ($opt =~ /^([_A-Z]+)=/) {
$set_D_opts{$1} = 1;
}
}
if (!$set_D_opts{MAXACTION}) {
push @$D_opts, "MAXACTION=100000";
}
if (!$set_D_opts{MAXMAPENTRIES}) {
push @$D_opts, "MAXMAPENTRIES=5000";
}
if (!$set_D_opts{MAXBACKTRACE}) {
push @$D_opts, "MAXBACKTRACE=200";
}
my $infile;
if (!defined $src) {
$infile = shift
or die "No input file specified.\n";
$src = read_src_file($infile);
} else {
$infile = "-e";
}
my (%StdVars, %UsedLibs, %DSOs, %LibPaths, %UsedStdVars);
my @stap_opts;
if ($verbose) {
push @stap_opts, "-v";
}
if ($d_opts) {
for my $opt (@$d_opts) {
push @stap_opts, '-d', $opt;
}
}
if (defined $skip_badvars) {
push @stap_opts, "--skip-badvars";
}
for my $opt (@$D_opts) {
push @stap_opts, "-D$opt";
}
if (defined $exec_path) {
if (!-f $exec_path) {
die "$exec_path not found.\n";
}
$StdVars{exec_path} = $exec_path;
push @stap_opts, '-d', $exec_path;
open my $in, "ldd $exec_path|"
or die "cannot run the command \"ldd $exec_path\": $!\n";
while (<$in>) {
if (m{\s+(\/\S+\.so(?:\.\d+)*)}) {
my $path = $1;
#warn "Found DSO $path.\n";
$DSOs{$path} = 1;
}
}
for my $path (sort keys %DSOs) {
push @stap_opts, '-d', $path;
}
close $in;
}
if (defined $pid) {
if (defined $master_pid) {
die "-x <pid> and --master <pid> are exclusive.\n";
}
push @stap_opts, "-x", $pid;
my $exec_file = "/proc/$pid/exe";
if (!-f $exec_file) {
die "Nginx process $pid is not running or ",
"you do not have enough permissions.\n";
}
$StdVars{pid_ok} = gen_pid_test_condition();
$StdVars{target} = $pid;
if (!defined $exec_path) {
$exec_path = readlink $exec_file;
$StdVars{exec_path} = $exec_path;
push @stap_opts, "-d", $exec_path;
}
process_dso($pid);
}
if (defined $master_pid) {
#push @stap_opts, "-x", $master_pid;
my $exec_file = "/proc/$master_pid/exe";
if (!-f $exec_file) {
die "Nginx process $master_pid is not running or ",
"you do not have enough permissions.\n";
}
if (!defined $exec_path) {
$exec_path = readlink $exec_file;
$StdVars{exec_path} = $exec_path;
push @stap_opts, "-d", $exec_path;
}
# process DSO files
my @pids = get_child_processes($master_pid);
if (@pids == 0) {
die "No child processes found for $master_pid.\n";
}
$StdVars{pid_ok} = gen_pid_test_condition(\@pids);
$StdVars{target} = "@pids";
my $pid = $pids[0];
process_dso($pid);
}
if ($sample_pid) {
process_dso($sample_pid);
}
if (!defined $StdVars{pid_ok} && defined $exec_path) {
$StdVars{pid_ok} = '1';
}
if (!defined $StdVars{target} && defined $exec_path) {
$StdVars{target} = 'ANY';
}
if (!$print_args) {
while (my ($k, $v) = each %$args) {
#warn "getting $k => $v";
$StdVars{"arg_$k"} = $v;
}
}
my %used_args;
my $stap_src = process_src($infile, $src);
if ($dump_src) {
print $stap_src;
exit;
}
if ($print_args) {
for my $name (sort keys %used_args) {
my $default = $used_args{$name};
print "\t--arg $name=VALUE";
if (defined $default) {
print " (default: $default)\n";
} else {
print "\n";
}
}
exit;
}
for my $key (keys %$args) {
if (!$UsedStdVars{"arg_$key"}) {
my $val = $args->{$key};
if (!defined $val) {
$val = '';
}
warn "WARNING: \$^arg_$key is defined by \"--arg $key=$val\", "
."but never used.\n";
}
}
my $tmpdir = tempdir("stapxx-XXXXXXXX", CLEANUP => 1);
while (my ($lib, $src) = each %UsedLibs) {
my $outfile = "$tmpdir/$lib.stp";
open my $out, ">$outfile"
or die "Cannot open $outfile for writing: $!\n";
print $out $src;
close $out;
}
push @stap_opts, "-I", $tmpdir;
if (defined $shcmd) {
push @stap_opts, "-c", $shcmd;
}
my $cmd = "stap " . quote_sh_args(\@stap_opts) . " -";
#warn $cmd;
open my $in, "|$cmd"
or die "Cannot run stap: $!\n";
print $in $stap_src;
close $in;
sub eval_usr_var {
my ($file, $usr_vars, $var) = @_;
if (defined $usr_vars->{$var}) {
return $usr_vars->{$var};
}
die "$file: line $.: Undefined user varaible \$*$var.\n";
}
sub eval_std_var {
my ($file, $var, $trait_name, $trait_val) = @_;
$UsedStdVars{$var} = 1;
if (defined $StdVars{$var}) {
return $StdVars{$var};
}
if (defined $trait_name) {
#warn "trait: $trait_name";
if ($trait_name eq 'default') {
if ($print_args && $var =~ /^arg_(\w+)$/) {
$used_args{$1} = $trait_val;
}
$StdVars{$var} = $trait_val;
return $trait_val;
} else {
die "$file: line $.: unknown trait name: $trait_name\n";
}
}
if ($print_args) {
if ($var =~ /^arg_(\w+)$/) {
$used_args{$1} = undef;
}
return '';
}
if ($var eq 'exec_path') {
die "$file: line $.: \$^exec_path is used but neither -x <pid> ",
"nor --exec <path> is specified.\n";
} elsif ($var =~ /^arg_(\w+)$/) {
die "$file: line $.: \$^$var is used but no --arg $1=VAL option is specified.\n";
} elsif ($var =~ /^(lib\w+)_path$/) {
my $prefix = $1;
my $libpath = find_dso_path($prefix);
if (!$libpath) {
warn "$file: line $.: $prefix is not found, assuming it is statically linked.\n";
if (!defined $StdVars{exec_path}) {
die "No -x <pid> option is specified.\n";
}
$LibPaths{$prefix} = $StdVars{exec_path};
return $StdVars{exec_path};
}
return $libpath;
} else {
die "$file: line $.: Undefined built-in variable \$^$var.\n";
}
}
sub find_dso_path {
my $pat = shift;
my $path = $LibPaths{$pat};
if ($path) {
return $path;
}
my $name;
if ($pat !~ /^lib(\S+)/) {
die "bad pattern: $pat";
}
$name = $1;
my $found_path;
for my $path (sort keys %DSOs) {
#warn "checking $path against $pat";
if ($path =~ m{\blib\Q$name\E[-.\d]*\.so(?:\.\d+)*$}) {
$LibPaths{$pat} = $path;
$found_path = $path;
warn "Found exact match for $pat: $path\n";
last;
}
if ($path =~ m{\b(?:lib)?\Q$name\E[^/\s]*?\.so(?:\.\d+)*$}) {
if ($found_path) {
warn "Ignored ambiguous library $path for \"$pat\"\n";
next;
}
$LibPaths{$pat} = $path;
$found_path = $path;
}
}
return $found_path;
}
sub read_src_file {
my $infile = shift;
open my $in, $infile
or die "Cannot open $infile for reading: $!\n";
my $src = do { local $/; <$in> };
close $in;
return $src;
}
sub use_libs {
my ($file, $libs) = @_;
#warn "libs: $libs";
my @libs = split /\s*,\s*/, $libs;
for my $lib (@libs) {
#warn "processing $lib...";
my $path = join("/", split /\./, $lib) . ".sxx";
#warn $path;
for my $dir (@$Inc) {
my $abspath = File::Spec->catfile($dir, $path);
#warn "Testing $abspath\n";
#warn "exist: ", (-f $abspath) ? 1 : 0;
if (-f $abspath) {
my $src = read_src_file($abspath);
$UsedLibs{$lib} = process_src($abspath, $src);
goto next_lib;
}
}
die "$file: line $.: cannot find \@user24 library $lib\n";
next_lib:
}
return "";
}
sub process_src {
my ($file, $src) = @_;
my %usr_vars;
my @bits;
my $libname_pat = qr/(?:\w+(?:\.\w+)*)/;
# process the input file
open my $in, '<', \$src or die $!;
while (<$in>) {
if ($. == 1 && /^\#!/) {
$_ = "#!/usr/bin/env stap\n";
next;
}
s{\$\^(arg_\w+)(?:\s*:(\w+)\s*\((.*?)\))?}{eval_std_var($file, $1, $2, $3)}eg;
s{\@pfunc\s*\(\s*(\w+)\s*\)}{process("\$^exec_path").function("$1")}g;
s{\$\^(\w+|lib[-.\w]+_path)(?:\s*:(\w+)\s*\((.*?)\))?}{eval_std_var($file, $1, $2, $3)}eg;
s{\$\*(\w+)\s*:=\s*(\&?\@(?:cast|var)\(.*?\)(?:\[\d+\])?)}{$usr_vars{$1} = $2; ""}eg;
s{\$\*(\w+)}{eval_usr_var($file, \%usr_vars, $1)}eg;
s{\@use\s+($libname_pat(?:\s*,\s*$libname_pat)*)}{use_libs($file, $1)}eg;
} continue {
push @bits, $_;
}
close $in;
return join '', @bits;
}
sub usage {
return <<'_EOC_';
Usage:
stap++ [optoins] [infile]
Options:
--arg NM=VAL Specify extra user arguments (for $^arg_NM).
--args Print all available arguments for --arg.
-c CMD start the probes, run CMD, and exit when it finishes
-d PATH Load debug info for the specified objects
-D NM=VAL Emit macro definition into generated C code.
-e SCRIPT Run given script.
--exec PATH Specify the executable file path to be traced.
--help Print this help.
-I PATH Specify the stap++ tapset library search directory.
--master PID Specify the master pid whose child processes are traced.
--sample-pid PID Sample process to inspect DSO objects to load via -d
-v Be verbose.
-x PID Sets target() to PID (also for $^exec_path and $^libxxx_path).
Examples:
stap++ -x 12345 -e 'probe begin { println("hello") exit() }'
stap++ -x 12345 infile.ss
_EOC_
}
sub get_child_processes {
my $pid = shift;
my @files = glob "/proc/[0-9]*/stat";
my @children;
for my $file (@files) {
#print "file: $file\n";
if ($file =~ m{^/proc/$pid/}) {
next;
}
open my $in, $file or next;
my $line = <$in>;
close $in;
if ($line =~ /^(\d+) \S+ \S+ (\d+)/) {
my ($child, $parent) = ($1, $2);
if ($parent eq $pid) {
push @children, $child;
}
}
}
@children = sort { $a <=> $b } @children;
return @children;
}
sub gen_pid_test_condition {
my $pids = shift;
if (!$pids) {
return "pid() == target()";
}
my @c;
for my $pid (@$pids) {
push @c, "pid() == $pid";
}
return '(' . join(" || ", @c) . ')';
}
sub process_dso {
my $pid = shift;
my $maps_file = "/proc/$pid/maps";
open my $in, $maps_file
or die "Cannot open $maps_file for reading: $!\n";
while (<$in>) {
if (m{\S+\.so(?:\.\d+)*$}) {
my $path = $&;
$DSOs{$path} = 1;
#warn "seeing $path";
}
}
for my $path (sort keys %DSOs) {
push @stap_opts, "-d", $path;
}
}
sub quote_sh_args ($) {
my ($args) = @_;
for my $arg (@$args) {
if ($arg =~ m{^[- "&%;,|?*.+=\w:/()]*$}) {
if ($arg =~ /[ "&%;,|?*()]/) {
$arg = "'$arg'";
}
next;
}
$arg =~ s/\\/\\\\/g;
$arg =~ s/'/\\'/g;
$arg =~ s/\n/\\n/g;
$arg =~ s/\r/\\r/g;
$arg =~ s/\t/\\t/g;
$arg = "\$'$arg'";
}
return "@$args";
}
你们觉得怎么样
顺便发一个小福利,打开 win10 设置,结束掉 explorer,然后设置里面还能用默认的微软拼音
还有 chinaunix 的百度百科里面说明了定期生成静态页面来减少服务器负载,说明依赖 react.js 还有其他出路
temporary picture r 站压缩图片太厉害了临时给手机传个照片都不可以
作者在阿里巴巴上过班可以介绍内推啊支付宝肯定有工作一定是作者自私自利不愿意分享,像我大专都还没说话;不支持 IE8 或者 IE11,对了建议大家在没有必要的情况下关闭浏览器的硬件加速,IE 浏览器在 F12 里面仿真,左上角保存仿真设置
我现在把 voidlinux 当成简版 opensuse 来用因为 opensuse 好像很混乱,wiki 乱写
只要谷歌放弃疯狂赞助 python 一切都会好起来的
现在我终于比人工智能值钱了!!!
现在人工智能已经收费高了,你认为中美欧人工智能差距大另说
除了顽固份子博客园,几乎没人用 ASP
隔壁 chinaunix 也升级停服了真是的国内脚本论坛怎么这么难全靠 php 支撑
习惯写脚本语言没有心思学 java 或者 c#,广东的大学学计算机学费超贵
这个系统更新比较频繁
对了我专业不是软工,自学 perl 来这里是为了添加人气
sqlite3 很简单啊看 ruby 的 gem 页面介绍就可以了
交流电不值钱,大专学的水利水电工程
可能是我的手机和电信诈骗团伙在同一个小区的网络里面还没有出 10.0.0.???网络的时候被入侵了
推荐访问 global 点 v2ex 点 co,必须加安全链接
大部分依赖处理器和操作系统编译优化,实在不行用显卡计算,你看人工智能依赖的硬件变好之后连 js 这种烂货都能天天用,以前 js 都是在比烂链最后的
欢迎使用 perl5 的 mojolicious 框架
看来你是 ruby 的粉丝建议你好好学习 perl,但是 perl6 基本没多少人用
主要是网上教如何写一个 Excel 的教程太多让我失去信心,但是一看 php 版本还是 8,我对生活又充满了信心
你看你上传的图片都压缩成什么样子了我还以为是我老旧的浏览器有问题
日常批评 java 占内存实在是太高了
如果需要电脑被常见 linux 病毒感染可以临时使用一下
对不起发帖时间电脑中了盗号木马并被骗钱了现在基本修好电脑了
以前没用过四核以上的电脑
你该不会连 sqlite 也没用过吧
opensuse 和 fedora 都有常见 gem 的打包