Token导航 LogoToken导航TokenDH.com
研究检索需要联网clawhub未标认证来源可访问clear审计通过

fix-erlang-ssh-cve-erlang-otp-behaviors修复 erlang ssh cve erlang otp 行为

Agent Skill

fix-erlang-ssh-cve-erlang-otp-behaviors 用于查找、检索和筛选相关信息,适合在 OpenClaw 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

2,280

周安装

95

GitHub Stars

公开资料未说明

下载量

760
OpenClaw

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

MIT-0

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:fix-erlang-ssh-cve-erlang-otp-behaviors(修复 erlang ssh cve erlang otp 行为)
来源仓库:https://github.com/wu-uk/fix-erlang-ssh-cve-erlang-otp-behaviors
安装命令:
openclaw skills install fix-erlang-ssh-cve-erlang-otp-behaviors
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 OpenClaw 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

ClawHubOpenClaw
openclaw skills install fix-erlang-ssh-cve-erlang-otp-behaviors

简介

fix-erlang-ssh-cve-erlang-otp-behaviors 用于查找 otp 行为相关信息。

  • 适用于 gen_server、gen_statem 等有状态进程开发。
  • 通过 clawhub 安装,结合来源仓库和 README 核验具体用法。
  • 安装前建议确认权限范围、维护状态及是否触发联网或文件读写。
  • 适用宿主包括 OpenClaw,接入前应确认版本、权限和运行环境要求。

SKILL.md

name
erlang-otp-behaviors
description
Use when oTP behaviors including gen_server for stateful processes, gen_statem for state machines, supervisors for fault tolerance, gen_event for event handling, and building robust, production-ready Erlang applications with proven patterns.

Erlang OTP Behaviors

Introduction

OTP (Open Telecom Platform) behaviors provide reusable patterns for common process types in Erlang systems. These abstractions handle complex details like message passing, error handling, and state management, allowing developers to focus on business logic while maintaining system reliability.

Behaviors define interfaces that processes must implement, with OTP handling the infrastructure. Gen_server provides client-server processes, gen_statem implements state machines, supervisors manage process lifecycles, and gen_event coordinates event distribution. Understanding these patterns is essential for production Erlang.

This skill covers gen_server for stateful processes, gen_statem for complex state machines, supervisor trees for fault tolerance, gen_event for event handling, application behavior for packaging, and patterns for building robust OTP systems.

Gen_Server Basics

Gen_server implements client-server processes with synchronous and asynchronous communication.

-module(counter_server).
-behaviour(gen_server).

%% API
-export([start_link/0, increment/0, decrement/0, get_value/0, reset/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-define(SERVER, ?MODULE).

%% State record
-record(state, {count = 0}).

%%%===================================================================
%%% API
%%%===================================================================

start_link() ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

increment() ->
    gen_server:cast(?SERVER, increment).

decrement() ->
    gen_server:cast(?SERVER, decrement).

get_value() ->
    gen_server:call(?SERVER, get_value).

reset() ->
    gen_server:call(?SERVER, reset).

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

init([]) ->
    {ok, #state{}}.

%% Synchronous calls (with response)
handle_call(get_value, _From, State) ->
    {reply, State#state.count, State};

handle_call(reset, _From, State) ->
    {reply, ok, State#state{count = 0}};

handle_call(_Request, _From, State) ->
    {reply, ignored, State}.

%% Asynchronous casts (no response)
handle_cast(increment, State) ->
    NewCount = State#state.count + 1,
    {noreply, State#state{count = NewCount}};

handle_cast(decrement, State) ->
    NewCount = State#state.count - 1,
    {noreply, State#state{count = NewCount}};

handle_cast(_Msg, State) ->
    {noreply, State}.

%% Handle other messages
handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

%%%===================================================================
%%% Complex gen_server example: Cache
%%%===================================================================

-module(cache_server).
-behaviour(gen_server).

-export([start_link/1, put/2, get/1, delete/1, clear/0, size/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-record(state, {
    cache = #{},
    max_size = 1000,
    hits = 0,
    misses = 0
}).

start_link(MaxSize) ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [MaxSize], []).

put(Key, Value) ->
    gen_server:call(?MODULE, {put, Key, Value}).

get(Key) ->
    gen_server:call(?MODULE, {get, Key}).

delete(Key) ->
    gen_server:cast(?MODULE, {delete, Key}).

clear() ->
    gen_server:cast(?MODULE, clear).

size() ->
    gen_server:call(?MODULE, size).

init([MaxSize]) ->
    process_flag(trap_exit, true),
    {ok, #state{max_size = MaxSize}}.

handle_call({put, Key, Value}, _From, State) ->
    Cache = State#state.cache,
    case maps:size(Cache) >= State#state.max_size of
        true ->
            {reply, {error, cache_full}, State};
        false ->
            NewCache = maps:put(Key, Value, Cache),
            {reply, ok, State#state{cache = NewCache}}
    end;

handle_call({get, Key}, _From, State) ->
    Cache = State#state.cache,
    case maps:find(Key, Cache) of
        {ok, Value} ->
            NewState = State#state{hits = State#state.hits + 1},
            {reply, {ok, Value}, NewState};
        error ->
            NewState = State#state{misses = State#state.misses + 1},
            {reply, not_found, NewState}
    end;

handle_call(size, _From, State) ->
    Size = maps:size(State#state.cache),
    {reply, Size, State};

handle_call(_Request, _From, State) ->
    {reply, {error, unknown_request}, State}.

handle_cast({delete, Key}, State) ->
    NewCache = maps:remove(Key, State#state.cache),
    {noreply, State#state{cache = NewCache}};

handle_cast(clear, State) ->
    {noreply, State#state{cache = #{}}};

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(Reason, State) ->
    io:format("Cache terminating: ~p~n", [Reason]),
    io:format("Stats - Hits: ~p, Misses: ~p~n", [State#state.hits, State#state.misses]),
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

%%%===================================================================
%%% gen_server with timeouts
%%%===================================================================

-module(session_server).
-behaviour(gen_server).

-export([start_link/0, touch/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-define(TIMEOUT, 30000). % 30 seconds

-record(state, {
    last_activity,
    data = #{}
}).

start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

touch() ->
    gen_server:cast(?MODULE, touch).

init([]) ->
    {ok, #state{last_activity = erlang:system_time(millisecond)}, ?TIMEOUT}.

handle_call(_Request, _From, State) ->
    {reply, ok, State, ?TIMEOUT}.

handle_cast(touch, State) ->
    NewState = State#state{last_activity = erlang:system_time(millisecond)},
    {noreply, NewState, ?TIMEOUT};

handle_cast(_Msg, State) ->
    {noreply, State, ?TIMEOUT}.

handle_info(timeout, State) ->
    io:format("Session timed out~n"),
    {stop, normal, State};

handle_info(_Info, State) ->
    {noreply, State, ?TIMEOUT}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

Gen_server provides structure for stateful processes with client-server patterns.

Gen_Statem for State Machines

Gen_statem implements finite state machines with explicit state transitions.

-module(door_fsm).
-behaviour(gen_statem).

-export([start_link/0, open/0, close/0, lock/0, unlock/1]).
-export([init/1, callback_mode/0, terminate/3, code_change/4]).
-export([locked/3, unlocked/3, open/3]).

-define(CODE, "1234").

start_link() ->
    gen_statem:start_link({local, ?MODULE}, ?MODULE, [], []).

open() ->
    gen_statem:call(?MODULE, open).

close() ->
    gen_statem:call(?MODULE, close).

lock() ->
    gen_statem:call(?MODULE, lock).

unlock(Code) ->
    gen_statem:call(?MODULE, {unlock, Code}).

init([]) ->
    {ok, locked, #{}}.

callback_mode() ->
    state_functions.

%% Locked state
locked(call, {unlock, Code}, Data) when Code =:= ?CODE ->
    {next_state, unlocked, Data, [{reply, ok}]};

locked(call, {unlock, _WrongCode}, Data) ->
    {keep_state, Data, [{reply, {error, wrong_code}}]};

locked(call, _Event, Data) ->
    {keep_state, Data, [{reply, {error, door_locked}}]}.

%% Unlocked state
unlocked(call, lock, Data) ->
    {next_state, locked, Data, [{reply, ok}]};

unlocked(call, open, Data) ->
    {next_state, open, Data, [{reply, ok}]};

unlocked(call, _Event, Data) ->
    {keep_state, Data, [{reply, ok}]}.

%% Open state
open(call, close, Data) ->
    {next_state, unlocked, Data, [{reply, ok}]};

open(call, _Event, Data) ->
    {keep_state, Data, [{reply, {error, door_open}}]}.

terminate(_Reason, _State, _Data) ->
    ok.

code_change(_OldVsn, State, Data, _Extra) ->
    {ok, State, Data}.

%%%===================================================================
%%% Connection state machine
%%%===================================================================

-module(connection_fsm).
-behaviour(gen_statem).

-export([start_link/0, connect/0, disconnect/0, send/1]).
-export([init/1, callback_mode/0, terminate/3, code_change/4]).
-export([disconnected/3, connecting/3, connected/3]).

-record(data, {
    socket = undefined,
    buffer = <<>>,
    retry_count = 0
}).

start_link() ->
    gen_statem:start_link({local, ?MODULE}, ?MODULE, [], []).

connect() ->
    gen_statem:call(?MODULE, connect).

disconnect() ->
    gen_statem:call(?MODULE, disconnect).

send(Data) ->
    gen_statem:call(?MODULE, {send, Data}).

init([]) ->
    {ok, disconnected, #data{}}.

callback_mode() ->
    [state_functions, state_enter].

%% Disconnected state
disconnected(enter, _OldState, _Data) ->
    io:format("Entered disconnected state~n"),
    keep_state_and_data;

disconnected(call, connect, Data) ->
    case connect_to_server() of
        {ok, Socket} ->
            {next_state, connected, Data#data{socket = Socket, retry_count = 0},
             [{reply, ok}]};
        error ->
            NewData = Data#data{retry_count = Data#data.retry_count + 1},
            case NewData#data.retry_count < 3 of
                true ->
                    {next_state, connecting, NewData, [{reply, {error, retrying}}]};
                false ->
                    {keep_state, NewData, [{reply, {error, max_retries}}]}
            end
    end.

%% Connecting state
connecting(enter, _OldState, _Data) ->
    erlang:send_after(1000, self(), retry_connect),
    keep_state_and_data;

connecting(info, retry_connect, Data) ->
    case connect_to_server() of
        {ok, Socket} ->
            {next_state, connected, Data#data{socket = Socket, retry_count = 0}};
        error ->
            NewData = Data#data{retry_count = Data#data.retry_count + 1},
            case NewData#data.retry_count < 3 of
                true ->
                    {keep_state, NewData};
                false ->
                    {next_state, disconnected, NewData}
            end
    end.

%% Connected state
connected(enter, _OldState, _Data) ->
    io:format("Connection established~n"),
    keep_state_and_data;

connected(call, {send, Data}, StateData) ->
    case send_data(StateData#data.socket, Data) of
        ok ->
            {keep_state_and_data, [{reply, ok}]};
        error ->
            {next_state, disconnected, StateData, [{reply, {error, send_failed}}]}
    end;

connected(call, disconnect, StateData) ->
    close_connection(StateData#data.socket),
    {next_state, disconnected, StateData#data{socket = undefined}, [{reply, ok}]}.

terminate(_Reason, _State, Data) ->
    case Data#data.socket of
        undefined -> ok;
        Socket -> close_connection(Socket)
    end.

code_change(_OldVsn, State, Data, _Extra) ->
    {ok, State, Data}.

%% Helper functions
connect_to_server() ->
    {ok, socket}.

send_data(_Socket, _Data) ->
    ok.

close_connection(_Socket) ->
    ok.

Gen_statem provides structured state machine implementation with explicit transitions.

Supervisor Trees

Supervisors monitor child processes and restart them on failure for fault tolerance.

-module(my_supervisor).
-behaviour(supervisor).

-export([start_link/0]).
-export([init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    SupFlags = #{
        strategy => one_for_one,
        intensity => 5,
        period => 60
    },

    ChildSpecs = [
        #{
            id => counter_server,
            start => {counter_server, start_link, []},
            restart => permanent,
            shutdown => 5000,
            type => worker,
            modules => [counter_server]
        },
        #{
            id => cache_server,
            start => {cache_server, start_link, [1000]},
            restart => permanent,
            shutdown => 5000,
            type => worker,
            modules => [cache_server]
        }
    ],

    {ok, {SupFlags, ChildSpecs}}.

%%%===================================================================
%%% Supervisor strategies
%%%===================================================================

%% one_for_one: Restart only failed child
init_one_for_one([]) ->
    SupFlags = #{strategy => one_for_one},
    Children = [worker_spec(worker1), worker_spec(worker2)],
    {ok, {SupFlags, Children}}.

%% one_for_all: Restart all children if any fails
init_one_for_all([]) ->
    SupFlags = #{strategy => one_for_all},
    Children = [worker_spec(worker1), worker_spec(worker2)],
    {ok, {SupFlags, Children}}.

%% rest_for_one: Restart failed child and all started after it
init_rest_for_one([]) ->
    SupFlags = #{strategy => rest_for_one},
    Children = [
        worker_spec(database),
        worker_spec(cache),  % Depends on database
        worker_spec(api)     % Depends on cache
    ],
    {ok, {SupFlags, Children}}.

worker_spec(Name) ->
    #{
        id => Name,
        start => {Name, start_link, []},
        restart => permanent,
        shutdown => 5000,
        type => worker
    }.

%%%===================================================================
%%% Nested supervisors (supervision tree)
%%%===================================================================

-module(app_supervisor).
-behaviour(supervisor).

-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    SupFlags = #{strategy => one_for_one},

    ChildSpecs = [
        #{
            id => database_sup,
            start => {database_supervisor, start_link, []},
            restart => permanent,
            type => supervisor
        },
        #{
            id => api_sup,
            start => {api_supervisor, start_link, []},
            restart => permanent,
            type => supervisor
        },
        #{
            id => worker_sup,
            start => {worker_supervisor, start_link, []},
            restart => permanent,
            type => supervisor
        }
    ],

    {ok, {SupFlags, ChildSpecs}}.

%%%===================================================================
%%% Dynamic supervision
%%%===================================================================

-module(dynamic_sup).
-behaviour(supervisor).

-export([start_link/0, start_child/1, stop_child/1]).
-export([init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

start_child(Args) ->
    supervisor:start_child(?MODULE, [Args]).

stop_child(Pid) ->
    supervisor:terminate_child(?MODULE, Pid).

init([]) ->
    SupFlags = #{
        strategy => simple_one_for_one,
        intensity => 5,
        period => 60
    },

    ChildSpec = #{
        id => worker,
        start => {worker, start_link, []},
        restart => temporary,
        shutdown => 5000,
        type => worker
    },

    {ok, {SupFlags, [ChildSpec]}}.

Supervisor trees provide automatic fault recovery and system resilience.

Best Practices

  1. Use gen_server for stateful processes to leverage OTP infrastructure and

error handling

  1. Implement all callback functions even if they return default values for

completeness

  1. Keep state records simple to reduce complexity and improve maintainability
  1. Use handle_cast for fire-and-forget operations without response requirements
  1. Implement proper termination in terminate/2 for resource cleanup
  1. Set appropriate timeout values to prevent indefinite blocking in calls
  1. Use gen_statem for complex state machines with many states and transitions
  1. Design supervisor hierarchies that match application component dependencies
  1. Use appropriate restart strategies based on child process relationships
  1. Test supervisor behavior by intentionally crashing children to verify

recovery

Common Pitfalls

  1. Blocking in handle_call prevents processing other messages causing deadlock
  1. Not matching all message patterns causes unhandled message accumulation
  1. Forgetting to reply in handle_call leaves callers waiting indefinitely
  1. Using wrong supervision strategy causes unnecessary process restarts
  1. Not setting process_flag trap_exit prevents graceful termination handling
  1. Creating circular dependencies in supervisor trees causes startup failures
  1. Using temporary restart for critical processes allows permanent failures
  1. Not implementing code_change prevents hot code upgrades
  1. Storing large state in gen_server causes memory issues
  1. Not handling timeout in state machines allows infinite blocking

When to Use This Skill

Apply gen_server for any stateful process requiring client-server interaction.

Use gen_statem when implementing protocols or systems with explicit state transitions.

Leverage supervisors for all applications requiring fault tolerance and automatic recovery.

Build supervisor trees to structure complex applications with multiple components.

Use OTP behaviors for production systems requiring reliability and maintainability.

Resources

适合场景

01

OpenClaw 用户查找和安装 Skill 时

02

用户想查找某类 Agent Skill 时

03

需要根据任务场景推荐可安装能力包时

04

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

OpenClaw

81.31%
按下载量换算618

安全审计

VirusTotal

通过

ClawScan

通过

Static analysis

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills