Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
X
XXL-JOB
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
靳帅
XXL-JOB
Commits
b30db360
提交
b30db360
authored
9月 15, 2018
作者:
xuxueli
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
新增任务运行模式 "GLUE模式(PowerShell) ",支持PowerShell脚本任务;
上级
e56731d7
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
431 行增加
和
3 行删除
+431
-3
XXL-JOB官方文档.md
doc/XXL-JOB官方文档.md
+2
-1
jobcode.index.ftl
...rc/main/webapp/WEB-INF/template/jobcode/jobcode.index.ftl
+3
-0
jobinfo.index.ftl
...rc/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl
+22
-1
jobinfo.index.1.js
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js
+4
-0
powershell.js
...p/static/plugins/codemirror/mode/powershell/powershell.js
+398
-0
GlueTypeEnum.java
...ore/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java
+2
-1
没有找到文件。
doc/XXL-JOB官方文档.md
浏览文件 @
b30db360
...
...
@@ -1241,7 +1241,8 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
-
25、任务调度备注中标注任务触发类型,如Cron触发、父任务触发、API触发等等,方便排查调度日志;
-
26、底层日志组件SimpleDateFormat线程安全问题修复;
-
27、执行器通讯线程优化,corePoolSize从256降低至32;
-
28、【迭代中】分片任务失败重试优化,仅重试当前失败的分片;
-
28、【迭代中】新增任务运行模式 "GLUE模式(PowerShell) ",支持PowerShell脚本任务;
-
29、【迭代中】分片任务失败重试优化,仅重试当前失败的分片;
### TODO LIST
...
...
xxl-job-admin/src/main/webapp/WEB-INF/template/jobcode/jobcode.index.ftl
浏览文件 @
b30db360
...
...
@@ -134,6 +134,9 @@
<
#
elseif
jobInfo
.
glueType =
=
"
GLUE_NODEJS
"
>
<
#
assign
glueTypeModeSrc =
"${request.contextPath}/static/plugins/codemirror/mode/javascript/javascript.js"
/>
<
#
assign
glueTypeIdeMode =
"text/javascript"
/>
<
#
elseif
jobInfo
.
glueType =
=
"
GLUE_POWERSHELL
"
>
<
#
assign
glueTypeModeSrc =
"${request.contextPath}/static/plugins/codemirror/mode/powershell/powershell.js"
/>
<
#
assign
glueTypeIdeMode =
"powershell"
/>
</
#
if>
...
...
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl
浏览文件 @
b30db360
...
...
@@ -268,7 +268,28 @@ console.log("${I18n.jobinfo_shard_total}: " + arguments[4])
console.log("Good bye!")
process.exit(0)
</textarea>
</textarea>
<textarea
class=
"glueSource_powershell"
style=
"display:none;"
>
Write-Host "xxl-job: hello powershell"
if($args.Count -eq 3) {
$executorparam = $args[0]
$shard_index = $args[1]
$shard_total = $args[2]
} Else {
$executorparam = ""
$shard_index = $args[0]
$shard_total = $args[1]
}
Write-Host "${I18n.jobinfo_script_location}: " $MyInvocation.MyCommand.Definition
Write-Host "${I18n.jobinfo_field_executorparam}: " $executorparam
Write-Host "${I18n.jobinfo_shard_index}: " $shard_index
Write-Host "${I18n.jobinfo_shard_total}: " $shard_total
Write-Host "Good bye!"
exit 0
</textarea>
</form>
</div>
</div>
...
...
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js
浏览文件 @
b30db360
...
...
@@ -374,6 +374,10 @@ $(function() {
$
(
"#addModal .form textarea[name='glueSource']"
).
val
(
$
(
"#addModal .form .glueSource_php"
).
val
()
);
}
else
if
(
'GLUE_NODEJS'
==
glueType
){
$
(
"#addModal .form textarea[name='glueSource']"
).
val
(
$
(
"#addModal .form .glueSource_nodejs"
).
val
()
);
}
else
if
(
'GLUE_POWERSHELL'
==
glueType
){
$
(
"#addModal .form textarea[name='glueSource']"
).
val
(
$
(
"#addModal .form .glueSource_powershell"
).
val
()
);
}
else
{
$
(
"#addModal .form textarea[name='glueSource']"
).
val
(
""
);
}
});
...
...
xxl-job-admin/src/main/webapp/static/plugins/codemirror/mode/powershell/powershell.js
0 → 100644
浏览文件 @
b30db360
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(
function
(
mod
)
{
'use strict'
;
if
(
typeof
exports
==
'object'
&&
typeof
module
==
'object'
)
// CommonJS
mod
(
require
(
'../../lib/codemirror'
));
else
if
(
typeof
define
==
'function'
&&
define
.
amd
)
// AMD
define
([
'../../lib/codemirror'
],
mod
);
else
// Plain browser env
mod
(
window
.
CodeMirror
);
})(
function
(
CodeMirror
)
{
'use strict'
;
CodeMirror
.
defineMode
(
'powershell'
,
function
()
{
function
buildRegexp
(
patterns
,
options
)
{
options
=
options
||
{};
var
prefix
=
options
.
prefix
!==
undefined
?
options
.
prefix
:
'^'
;
var
suffix
=
options
.
suffix
!==
undefined
?
options
.
suffix
:
'
\\
b'
;
for
(
var
i
=
0
;
i
<
patterns
.
length
;
i
++
)
{
if
(
patterns
[
i
]
instanceof
RegExp
)
{
patterns
[
i
]
=
patterns
[
i
].
source
;
}
else
{
patterns
[
i
]
=
patterns
[
i
].
replace
(
/
[
-
\/\\
^$*+?.()|[
\]
{}
]
/g
,
'
\\
$&'
);
}
}
return
new
RegExp
(
prefix
+
'('
+
patterns
.
join
(
'|'
)
+
')'
+
suffix
,
'i'
);
}
var
notCharacterOrDash
=
'(?=[^A-Za-z
\\
d
\\
-_]|$)'
;
var
varNames
=
/
[\w\-
:
]
/
var
keywords
=
buildRegexp
([
/begin|break|catch|continue|data|default|do|dynamicparam/
,
/else|elseif|end|exit|filter|finally|for|foreach|from|function|if|in/
,
/param|process|return|switch|throw|trap|try|until|where|while/
],
{
suffix
:
notCharacterOrDash
});
var
punctuation
=
/
[\[\]
{},;`
\.]
|@
[
({
]
/
;
var
wordOperators
=
buildRegexp
([
'f'
,
/b
?
not/
,
/
[
ic
]?
split/
,
'join'
,
/is
(
not
)?
/
,
'as'
,
/
[
ic
]?(
eq|ne|
[
gl
][
te
])
/
,
/
[
ic
]?(
not
)?(
like|match|contains
)
/
,
/
[
ic
]?
replace/
,
/b
?(
and|or|xor
)
/
],
{
prefix
:
'-'
});
var
symbolOperators
=
/
[
+
\-
*
\/
%
]
=|
\+\+
|--|
\.\.
|
[
+
\-
*&^%:=!|
\/]
|<
(?!
#
)
|
(?!
#
)
>/
;
var
operators
=
buildRegexp
([
wordOperators
,
symbolOperators
],
{
suffix
:
''
});
var
numbers
=
/^
((
0x
[\d
a-f
]
+
)
|
((\d
+
\.\d
+|
\d\.
|
\.\d
+|
\d
+
)(
e
[\+\-]?\d
+
)?))[
ld
]?([
kmgtp
]
b
)?
/i
;
var
identifiers
=
/^
[
A-Za-z
\_][
A-Za-z
\-\_\d]
*
\b
/
;
var
symbolBuiltins
=
/
[
A-Z
]
:|%|
\?
/i
;
var
namedBuiltins
=
buildRegexp
([
/Add-
(
Computer|Content|History|Member|PSSnapin|Type
)
/
,
/Checkpoint-Computer/
,
/Clear-
(
Content|EventLog|History|Host|Item
(
Property
)?
|Variable
)
/
,
/Compare-Object/
,
/Complete-Transaction/
,
/Connect-PSSession/
,
/ConvertFrom-
(
Csv|Json|SecureString|StringData
)
/
,
/Convert-Path/
,
/ConvertTo-
(
Csv|Html|Json|SecureString|Xml
)
/
,
/Copy-Item
(
Property
)?
/
,
/Debug-Process/
,
/Disable-
(
ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration
)
/
,
/Disconnect-PSSession/
,
/Enable-
(
ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration
)
/
,
/
(
Enter|Exit
)
-PSSession/
,
/Export-
(
Alias|Clixml|Console|Counter|Csv|FormatData|ModuleMember|PSSession
)
/
,
/ForEach-Object/
,
/Format-
(
Custom|List|Table|Wide
)
/
,
new
RegExp
(
'Get-(Acl|Alias|AuthenticodeSignature|ChildItem|Command|ComputerRestorePoint|Content|ControlPanelItem|Counter|Credential'
+
'|Culture|Date|Event|EventLog|EventSubscriber|ExecutionPolicy|FormatData|Help|History|Host|HotFix|Item|ItemProperty|Job'
+
'|Location|Member|Module|PfxCertificate|Process|PSBreakpoint|PSCallStack|PSDrive|PSProvider|PSSession|PSSessionConfiguration'
+
'|PSSnapin|Random|Service|TraceSource|Transaction|TypeData|UICulture|Unique|Variable|Verb|WinEvent|WmiObject)'
),
/Group-Object/
,
/Import-
(
Alias|Clixml|Counter|Csv|LocalizedData|Module|PSSession
)
/
,
/ImportSystemModules/
,
/Invoke-
(
Command|Expression|History|Item|RestMethod|WebRequest|WmiMethod
)
/
,
/Join-Path/
,
/Limit-EventLog/
,
/Measure-
(
Command|Object
)
/
,
/Move-Item
(
Property
)?
/
,
new
RegExp
(
'New-(Alias|Event|EventLog|Item(Property)?|Module|ModuleManifest|Object|PSDrive|PSSession|PSSessionConfigurationFile'
+
'|PSSessionOption|PSTransportOption|Service|TimeSpan|Variable|WebServiceProxy|WinEvent)'
),
/Out-
(
Default|File|GridView|Host|Null|Printer|String
)
/
,
/Pause/
,
/
(
Pop|Push
)
-Location/
,
/Read-Host/
,
/Receive-
(
Job|PSSession
)
/
,
/Register-
(
EngineEvent|ObjectEvent|PSSessionConfiguration|WmiEvent
)
/
,
/Remove-
(
Computer|Event|EventLog|Item
(
Property
)?
|Job|Module|PSBreakpoint|PSDrive|PSSession|PSSnapin|TypeData|Variable|WmiObject
)
/
,
/Rename-
(
Computer|Item
(
Property
)?)
/
,
/Reset-ComputerMachinePassword/
,
/Resolve-Path/
,
/Restart-
(
Computer|Service
)
/
,
/Restore-Computer/
,
/Resume-
(
Job|Service
)
/
,
/Save-Help/
,
/Select-
(
Object|String|Xml
)
/
,
/Send-MailMessage/
,
new
RegExp
(
'Set-(Acl|Alias|AuthenticodeSignature|Content|Date|ExecutionPolicy|Item(Property)?|Location|PSBreakpoint|PSDebug'
+
'|PSSessionConfiguration|Service|StrictMode|TraceSource|Variable|WmiInstance)'
),
/Show-
(
Command|ControlPanelItem|EventLog
)
/
,
/Sort-Object/
,
/Split-Path/
,
/Start-
(
Job|Process|Service|Sleep|Transaction|Transcript
)
/
,
/Stop-
(
Computer|Job|Process|Service|Transcript
)
/
,
/Suspend-
(
Job|Service
)
/
,
/TabExpansion2/
,
/Tee-Object/
,
/Test-
(
ComputerSecureChannel|Connection|ModuleManifest|Path|PSSessionConfigurationFile
)
/
,
/Trace-Command/
,
/Unblock-File/
,
/Undo-Transaction/
,
/Unregister-
(
Event|PSSessionConfiguration
)
/
,
/Update-
(
FormatData|Help|List|TypeData
)
/
,
/Use-Transaction/
,
/Wait-
(
Event|Job|Process
)
/
,
/Where-Object/
,
/Write-
(
Debug|Error|EventLog|Host|Output|Progress|Verbose|Warning
)
/
,
/cd|help|mkdir|more|oss|prompt/
,
/ac|asnp|cat|cd|chdir|clc|clear|clhy|cli|clp|cls|clv|cnsn|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|dnsn|ebp/
,
/echo|epal|epcsv|epsn|erase|etsn|exsn|fc|fl|foreach|ft|fw|gal|gbp|gc|gci|gcm|gcs|gdr|ghy|gi|gjb|gl|gm|gmo|gp|gps/
,
/group|gsn|gsnp|gsv|gu|gv|gwmi|h|history|icm|iex|ihy|ii|ipal|ipcsv|ipmo|ipsn|irm|ise|iwmi|iwr|kill|lp|ls|man|md/
,
/measure|mi|mount|move|mp|mv|nal|ndr|ni|nmo|npssc|nsn|nv|ogv|oh|popd|ps|pushd|pwd|r|rbp|rcjb|rcsn|rd|rdr|ren|ri/
,
/rjb|rm|rmdir|rmo|rni|rnp|rp|rsn|rsnp|rujb|rv|rvpa|rwmi|sajb|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls/
,
/sort|sp|spjb|spps|spsv|start|sujb|sv|swmi|tee|trcm|type|where|wjb|write/
],
{
prefix
:
''
,
suffix
:
''
});
var
variableBuiltins
=
buildRegexp
([
/
[
$?^_
]
|Args|ConfirmPreference|ConsoleFileName|DebugPreference|Error|ErrorActionPreference|ErrorView|ExecutionContext/
,
/FormatEnumerationLimit|Home|Host|Input|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount/
,
/MaximumHistoryCount|MaximumVariableCount|MyInvocation|NestedPromptLevel|OutputEncoding|Pid|Profile|ProgressPreference/
,
/PSBoundParameters|PSCommandPath|PSCulture|PSDefaultParameterValues|PSEmailServer|PSHome|PSScriptRoot|PSSessionApplicationName/
,
/PSSessionConfigurationName|PSSessionOption|PSUICulture|PSVersionTable|Pwd|ShellId|StackTrace|VerbosePreference/
,
/WarningPreference|WhatIfPreference/
,
/Event|EventArgs|EventSubscriber|Sender/
,
/Matches|Ofs|ForEach|LastExitCode|PSCmdlet|PSItem|PSSenderInfo|This/
,
/true|false|null/
],
{
prefix
:
'
\\
$'
,
suffix
:
''
});
var
builtins
=
buildRegexp
([
symbolBuiltins
,
namedBuiltins
,
variableBuiltins
],
{
suffix
:
notCharacterOrDash
});
var
grammar
=
{
keyword
:
keywords
,
number
:
numbers
,
operator
:
operators
,
builtin
:
builtins
,
punctuation
:
punctuation
,
identifier
:
identifiers
};
// tokenizers
function
tokenBase
(
stream
,
state
)
{
// Handle Comments
//var ch = stream.peek();
var
parent
=
state
.
returnStack
[
state
.
returnStack
.
length
-
1
];
if
(
parent
&&
parent
.
shouldReturnFrom
(
state
))
{
state
.
tokenize
=
parent
.
tokenize
;
state
.
returnStack
.
pop
();
return
state
.
tokenize
(
stream
,
state
);
}
if
(
stream
.
eatSpace
())
{
return
null
;
}
if
(
stream
.
eat
(
'('
))
{
state
.
bracketNesting
+=
1
;
return
'punctuation'
;
}
if
(
stream
.
eat
(
')'
))
{
state
.
bracketNesting
-=
1
;
return
'punctuation'
;
}
for
(
var
key
in
grammar
)
{
if
(
stream
.
match
(
grammar
[
key
]))
{
return
key
;
}
}
var
ch
=
stream
.
next
();
// single-quote string
if
(
ch
===
"'"
)
{
return
tokenSingleQuoteString
(
stream
,
state
);
}
if
(
ch
===
'$'
)
{
return
tokenVariable
(
stream
,
state
);
}
// double-quote string
if
(
ch
===
'"'
)
{
return
tokenDoubleQuoteString
(
stream
,
state
);
}
if
(
ch
===
'<'
&&
stream
.
eat
(
'#'
))
{
state
.
tokenize
=
tokenComment
;
return
tokenComment
(
stream
,
state
);
}
if
(
ch
===
'#'
)
{
stream
.
skipToEnd
();
return
'comment'
;
}
if
(
ch
===
'@'
)
{
var
quoteMatch
=
stream
.
eat
(
/
[
"'
]
/
);
if
(
quoteMatch
&&
stream
.
eol
())
{
state
.
tokenize
=
tokenMultiString
;
state
.
startQuote
=
quoteMatch
[
0
];
return
tokenMultiString
(
stream
,
state
);
}
else
if
(
stream
.
eol
())
{
return
'error'
;
}
else
if
(
stream
.
peek
().
match
(
/
[
({
]
/
))
{
return
'punctuation'
;
}
else
if
(
stream
.
peek
().
match
(
varNames
))
{
// splatted variable
return
tokenVariable
(
stream
,
state
);
}
}
return
'error'
;
}
function
tokenSingleQuoteString
(
stream
,
state
)
{
var
ch
;
while
((
ch
=
stream
.
peek
())
!=
null
)
{
stream
.
next
();
if
(
ch
===
"'"
&&
!
stream
.
eat
(
"'"
))
{
state
.
tokenize
=
tokenBase
;
return
'string'
;
}
}
return
'error'
;
}
function
tokenDoubleQuoteString
(
stream
,
state
)
{
var
ch
;
while
((
ch
=
stream
.
peek
())
!=
null
)
{
if
(
ch
===
'$'
)
{
state
.
tokenize
=
tokenStringInterpolation
;
return
'string'
;
}
stream
.
next
();
if
(
ch
===
'`'
)
{
stream
.
next
();
continue
;
}
if
(
ch
===
'"'
&&
!
stream
.
eat
(
'"'
))
{
state
.
tokenize
=
tokenBase
;
return
'string'
;
}
}
return
'error'
;
}
function
tokenStringInterpolation
(
stream
,
state
)
{
return
tokenInterpolation
(
stream
,
state
,
tokenDoubleQuoteString
);
}
function
tokenMultiStringReturn
(
stream
,
state
)
{
state
.
tokenize
=
tokenMultiString
;
state
.
startQuote
=
'"'
return
tokenMultiString
(
stream
,
state
);
}
function
tokenHereStringInterpolation
(
stream
,
state
)
{
return
tokenInterpolation
(
stream
,
state
,
tokenMultiStringReturn
);
}
function
tokenInterpolation
(
stream
,
state
,
parentTokenize
)
{
if
(
stream
.
match
(
'$('
))
{
var
savedBracketNesting
=
state
.
bracketNesting
;
state
.
returnStack
.
push
({
/*jshint loopfunc:true */
shouldReturnFrom
:
function
(
state
)
{
return
state
.
bracketNesting
===
savedBracketNesting
;
},
tokenize
:
parentTokenize
});
state
.
tokenize
=
tokenBase
;
state
.
bracketNesting
+=
1
;
return
'punctuation'
;
}
else
{
stream
.
next
();
state
.
returnStack
.
push
({
shouldReturnFrom
:
function
()
{
return
true
;
},
tokenize
:
parentTokenize
});
state
.
tokenize
=
tokenVariable
;
return
state
.
tokenize
(
stream
,
state
);
}
}
function
tokenComment
(
stream
,
state
)
{
var
maybeEnd
=
false
,
ch
;
while
((
ch
=
stream
.
next
())
!=
null
)
{
if
(
maybeEnd
&&
ch
==
'>'
)
{
state
.
tokenize
=
tokenBase
;
break
;
}
maybeEnd
=
(
ch
===
'#'
);
}
return
'comment'
;
}
function
tokenVariable
(
stream
,
state
)
{
var
ch
=
stream
.
peek
();
if
(
stream
.
eat
(
'{'
))
{
state
.
tokenize
=
tokenVariableWithBraces
;
return
tokenVariableWithBraces
(
stream
,
state
);
}
else
if
(
ch
!=
undefined
&&
ch
.
match
(
varNames
))
{
stream
.
eatWhile
(
varNames
);
state
.
tokenize
=
tokenBase
;
return
'variable-2'
;
}
else
{
state
.
tokenize
=
tokenBase
;
return
'error'
;
}
}
function
tokenVariableWithBraces
(
stream
,
state
)
{
var
ch
;
while
((
ch
=
stream
.
next
())
!=
null
)
{
if
(
ch
===
'}'
)
{
state
.
tokenize
=
tokenBase
;
break
;
}
}
return
'variable-2'
;
}
function
tokenMultiString
(
stream
,
state
)
{
var
quote
=
state
.
startQuote
;
if
(
stream
.
sol
()
&&
stream
.
match
(
new
RegExp
(
quote
+
'@'
)))
{
state
.
tokenize
=
tokenBase
;
}
else
if
(
quote
===
'"'
)
{
while
(
!
stream
.
eol
())
{
var
ch
=
stream
.
peek
();
if
(
ch
===
'$'
)
{
state
.
tokenize
=
tokenHereStringInterpolation
;
return
'string'
;
}
stream
.
next
();
if
(
ch
===
'`'
)
{
stream
.
next
();
}
}
}
else
{
stream
.
skipToEnd
();
}
return
'string'
;
}
var
external
=
{
startState
:
function
()
{
return
{
returnStack
:
[],
bracketNesting
:
0
,
tokenize
:
tokenBase
};
},
token
:
function
(
stream
,
state
)
{
return
state
.
tokenize
(
stream
,
state
);
},
blockCommentStart
:
'<#'
,
blockCommentEnd
:
'#>'
,
lineComment
:
'#'
,
fold
:
'brace'
};
return
external
;
});
CodeMirror
.
defineMIME
(
'application/x-powershell'
,
'powershell'
);
});
xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java
浏览文件 @
b30db360
...
...
@@ -10,7 +10,8 @@ public enum GlueTypeEnum {
GLUE_SHELL
(
"GLUE(Shell)"
,
true
,
"bash"
,
".sh"
),
GLUE_PYTHON
(
"GLUE(Python)"
,
true
,
"python"
,
".py"
),
GLUE_PHP
(
"GLUE(PHP)"
,
true
,
"php"
,
".php"
),
GLUE_NODEJS
(
"GLUE(Nodejs)"
,
true
,
"node"
,
".js"
);
GLUE_NODEJS
(
"GLUE(Nodejs)"
,
true
,
"node"
,
".js"
),
GLUE_POWERSHELL
(
"GLUE(PowerShell)"
,
true
,
"powershell "
,
".ps1"
);
private
String
desc
;
private
boolean
isScript
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论